Skip to content

Commit

Permalink
imp: remove pidinfo abstraction
Browse files Browse the repository at this point in the history
Problem: The `struct pidinfo` abstraction was only required by
the IMP kill subcommand, which has been removed.

Remove pidinfo related code and tests.
  • Loading branch information
grondo committed Nov 2, 2024
1 parent a340ec6 commit 3c33ecb
Show file tree
Hide file tree
Showing 3 changed files with 0 additions and 264 deletions.
227 changes: 0 additions & 227 deletions src/imp/pidinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,203 +25,12 @@

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#ifdef HAVE_LINUX_MAGIC_H
#include <linux/magic.h>
#endif
#ifndef TMPFS_MAGIC
#define TMPFS_MAGIC 0x01021994 /* from linux/magic.h */
#endif
#ifndef CGROUP_SUPER_MAGIC
#define CGROUP_SUPER_MAGIC 0x27e0eb
#endif

#include <pwd.h>
#include <signal.h>

#include "src/libutil/strlcpy.h"

#include "pidinfo.h"
#include "imp_log.h"

struct cgroup_info {
char mount_dir[PATH_MAX + 1];
bool unified;
};

/* Determine if this system is using the unified (v2) or legacy (v1)
* cgroups hierarchy (See https://systemd.io/CGROUP_DELEGATION/)
* and mount point for systemd managed cgroups.
*/
static int cgroup_info_init (struct cgroup_info *cg)
{
struct statfs fs;

(void) strlcpy (cg->mount_dir, "/sys/fs/cgroup", sizeof (cg->mount_dir));
cg->unified = true;

if (statfs (cg->mount_dir, &fs) < 0)
return -1;

#ifdef CGROUP2_SUPER_MAGIC
/* if cgroup2 fs mounted: unified hierarchy for all users of cgroupfs
*/
if (fs.f_type == CGROUP2_SUPER_MAGIC)
return 0;
#endif /* CGROUP2_SUPER_MAGIC */

/* O/w, if /sys/fs/cgroup is mounted as tmpfs, we need to check
* for /sys/fs/cgroup/systemd mounted as cgroupfs (legacy).
* We do not support hybrid mode (/sys/fs/cgroup/systemd or
* /sys/fs/cgroup/unified mounted as cgroup2fs), since there were
* no systems on which to test this configuration.
*/
if (fs.f_type == TMPFS_MAGIC) {

(void) strlcpy (cg->mount_dir,
"/sys/fs/cgroup/systemd",
sizeof (cg->mount_dir));
if (statfs (cg->mount_dir, &fs) == 0
&& fs.f_type == CGROUP_SUPER_MAGIC) {
cg->unified = false;
return 0;
}
}

/* Unable to determine cgroup mount point and/or unified vs legacy */
return -1;
}


/* Store the command name from /proc/PID/comm into buffer 'buf' of size 'len'.
*/
static int pid_command (pid_t pid, char *buf, int len)
{
int rc = -1;
FILE *fp = NULL;
int n;
size_t size = 0;
char *line = NULL;
char file [64];
int saved_errno;

if (buf == NULL || len <= 0) {
errno = EINVAL;
return -1;
}

/* 64 bytes is guaranteed to hold /proc/%ju/comm, assuming largest
* unsigned integer pid would be 21 characters (2^64-1) + 11 characters
* for "/proc/" + "/comm" + some slack.
*/
(void) snprintf (file, sizeof (file), "/proc/%ju/comm", (uintmax_t) pid);

if (!(fp = fopen (file, "r")))
return -1;
if (getline (&line, &size, fp) < 0)
goto out;
if ((n = strlen (line)) > len) {
errno = ENOSPC;
goto out;
}
/*
* Remove trailing newline and copy command into destination buffer.
* No need to check return code since size of destination was already
* checked above.
*/
if (line[n-1] == '\n')
line[n-1] = '\0';
(void) strlcpy (buf, line, len);

rc = 0;
out:
saved_errno = errno;
free (line);
fclose (fp);
errno = saved_errno;
return rc;
}

/*
* Looks up the 'name=systemd'[*] subsystem relative cgroup path in
* /proc/PID/cgroups and prepends `cgroup_mount_dir` to get the
* full path.
*
* [*] perhaps could also use the "pids" cgroup.
*/
static int pid_systemd_cgroup_path (pid_t pid, char *buf, int len)
{
int rc = -1;
FILE *fp;
size_t size = 0;
int n;
char file [64];
char *line = NULL;
struct cgroup_info cgroup;
int saved_errno;

if (cgroup_info_init (&cgroup) < 0)
return -1;

/* 64 bytes is guaranteed to hold /proc/%ju/comm, assuming largest
* unsigned integer pid would be 21 characters (2^64-1) + 13 characters
* for "/proc/" + "/cgroup" + some slack.
*/
(void) snprintf (file, sizeof (file), "/proc/%ju/cgroup", (uintmax_t) pid);
if (!(fp = fopen (file, "r")))
return -1;

while ((n = getline (&line, &size, fp)) >= 0) {
char *nl;
char *relpath = NULL;
char *subsys = strchr (line, ':');
if ((nl = strchr (line, '\n')))
*nl = '\0';
if (subsys == NULL || *(++subsys) == '\0'
|| !(relpath = strchr (subsys, ':')))
continue;
/* Nullify subsys, relpath is already nul-terminated at newline */
*(relpath++) = '\0';
if (cgroup.unified || strcmp (subsys, "name=systemd") == 0) {
n = snprintf (buf, len, "%s%s", cgroup.mount_dir, relpath);
if ((n > 0) && (n < len))
rc = 0;
break;
}
}

if (rc < 0)
errno = ENOENT;

saved_errno = errno;
free (line);
fclose (fp);
errno = saved_errno;
return rc;
}

/* return the file owner of 'path'
*/
static uid_t path_owner (const char *path)
{
struct stat st;
if (stat (path, &st) < 0)
return ((uid_t) -1);
return st.st_uid;
}

/* return the owner of pid. -1 on failure.
*/
static uid_t pid_owner (pid_t pid)
{
char path [64];

/* /proc/%ju is guaranteed to fit in 64 bytes:
*/
(void) snprintf (path, sizeof (path), "/proc/%ju", (uintmax_t) pid);
return path_owner (path);
}

static int parse_pid (const char *s, pid_t *ppid)
{
unsigned long val;
Expand Down Expand Up @@ -281,42 +90,6 @@ static pid_t pid_ppid (pid_t pid)
return ppid;
}

void pid_info_destroy (struct pid_info *pi)
{
if (pi) {
int saved_errno = errno;
free (pi);
errno = saved_errno;
}
}

struct pid_info *pid_info_create (pid_t pid)
{
struct pid_info *pi;

if (pid == 0) {
errno = EINVAL;
return NULL;
}
if (!(pi = calloc (1, sizeof (*pi))))
return NULL;
if (pid < 0)
pid = -pid;
pi->pid = pid;
if ((pi->pid_owner = pid_owner (pid)) == (uid_t) -1)
goto err;
if (pid_systemd_cgroup_path (pid, pi->cg_path, sizeof (pi->cg_path)) < 0)
goto err;
if ((pi->cg_owner = path_owner (pi->cg_path)) == (uid_t) -1)
goto err;
if (pid_command (pid, pi->command, sizeof (pi->command)) < 0)
goto err;
return pi;
err:
pid_info_destroy (pi);
return NULL;
}

int pid_kill_children_fallback (pid_t parent, int sig)
{
int count = 0;
Expand Down
11 changes: 0 additions & 11 deletions src/imp/pidinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,6 @@
#ifndef HAVE_PIDINFO_H
#define HAVE_PIDINFO_H 1

struct pid_info {
pid_t pid;
char command [64];
uid_t pid_owner;
char cg_path [4096];
uid_t cg_owner;
};

struct pid_info *pid_info_create (pid_t pid);
void pid_info_destroy (struct pid_info *pi);

/* Send signal to any children of pid.
* Returns the number of children signaled or -1 if an error occurred.
*/
Expand Down
26 changes: 0 additions & 26 deletions src/imp/test/pidinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,33 +149,7 @@ static void pid_kill_tests (void)

int main (void)
{
struct pid_info *p;

ok (pid_info_create (0) == NULL && errno == EINVAL,
"pid_info_create (0) fails with EINVAL");

ok ((p = pid_info_create (getpid ())) != NULL,
"pid_info_create (getpid ()) works");
ok (p->pid == getpid (),
"p->pid is expected");
ok (p->pid_owner == getuid (),
"p->pid_owner is expected");
diag ("p->cg_path = %s", p->cg_path);
diag ("p->cg_owner = %d", (int) p->cg_owner);
pid_info_destroy (p);

ok ((p = pid_info_create (-getpid ())) != NULL,
"pid_info_create (-getpid ()) works");
ok (p->pid == getpid (),
"p->pid is expected");
ok (p->pid_owner == getuid (),
"p->pid_owner is expected");
diag ("p->cg_path = %s", p->cg_path);
diag ("p->cg_owner = %d", (int) p->cg_owner);
pid_info_destroy (p);

pid_kill_tests ();

done_testing ();
}

Expand Down

0 comments on commit 3c33ecb

Please sign in to comment.