cgroup: honour sticky bit when trimming cgroup trees
This commit is contained in:
parent
94959f0fa0
commit
ad293f5a94
|
@ -153,17 +153,38 @@ int cg_read_subgroup(DIR *d, char **fn) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cg_rmdir(const char *controller, const char *path) {
|
int cg_rmdir(const char *controller, const char *path, bool honour_sticky) {
|
||||||
char *p;
|
char *p;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = cg_get_path(controller, path, NULL, &p)) < 0)
|
r = cg_get_path(controller, path, NULL, &p);
|
||||||
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (honour_sticky) {
|
||||||
|
char *tasks;
|
||||||
|
|
||||||
|
/* If the sticky bit is set don't remove the directory */
|
||||||
|
|
||||||
|
tasks = strappend(p, "/tasks");
|
||||||
|
if (!tasks) {
|
||||||
|
free(p);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = file_is_sticky(tasks);
|
||||||
|
free(tasks);
|
||||||
|
|
||||||
|
if (r > 0) {
|
||||||
|
free(p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r = rmdir(p);
|
r = rmdir(p);
|
||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
return r < 0 ? -errno : 0;
|
return (r < 0 && errno != ENOENT) ? -errno : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
|
int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
|
||||||
|
@ -302,7 +323,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si
|
||||||
ret = r;
|
ret = r;
|
||||||
|
|
||||||
if (rem)
|
if (rem)
|
||||||
if ((r = cg_rmdir(controller, path)) < 0) {
|
if ((r = cg_rmdir(controller, path, true)) < 0) {
|
||||||
if (ret >= 0 &&
|
if (ret >= 0 &&
|
||||||
r != -ENOENT &&
|
r != -ENOENT &&
|
||||||
r != -EBUSY)
|
r != -EBUSY)
|
||||||
|
@ -466,7 +487,7 @@ int cg_migrate_recursive(const char *controller, const char *from, const char *t
|
||||||
ret = r;
|
ret = r;
|
||||||
|
|
||||||
if (rem)
|
if (rem)
|
||||||
if ((r = cg_rmdir(controller, from)) < 0) {
|
if ((r = cg_rmdir(controller, from, true)) < 0) {
|
||||||
if (ret >= 0 &&
|
if (ret >= 0 &&
|
||||||
r != -ENOENT &&
|
r != -ENOENT &&
|
||||||
r != -EBUSY)
|
r != -EBUSY)
|
||||||
|
@ -543,7 +564,7 @@ int cg_trim(const char *controller, const char *path, bool delete_root) {
|
||||||
if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
|
if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = rm_rf(fs, true, delete_root);
|
r = rm_rf(fs, true, delete_root, true);
|
||||||
free(fs);
|
free(fs);
|
||||||
|
|
||||||
return r == -ENOENT ? 0 : r;
|
return r == -ENOENT ? 0 : r;
|
||||||
|
|
|
@ -52,7 +52,7 @@ int cg_get_by_pid(const char *controller, pid_t pid, char **path);
|
||||||
|
|
||||||
int cg_trim(const char *controller, const char *path, bool delete_root);
|
int cg_trim(const char *controller, const char *path, bool delete_root);
|
||||||
|
|
||||||
int cg_rmdir(const char *controller, const char *path);
|
int cg_rmdir(const char *controller, const char *path, bool honour_sticky);
|
||||||
int cg_delete(const char *controller, const char *path);
|
int cg_delete(const char *controller, const char *path);
|
||||||
|
|
||||||
int cg_create(const char *controller, const char *path);
|
int cg_create(const char *controller, const char *path);
|
||||||
|
|
|
@ -409,7 +409,7 @@ static int user_remove_runtime_path(User *u) {
|
||||||
if (!u->runtime_path)
|
if (!u->runtime_path)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = rm_rf(u->runtime_path, false, true);
|
r = rm_rf(u->runtime_path, false, true, false);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_error("Failed to remove runtime directory %s: %s", u->runtime_path, strerror(-r));
|
log_error("Failed to remove runtime directory %s: %s", u->runtime_path, strerror(-r));
|
||||||
|
|
||||||
|
|
|
@ -3073,7 +3073,7 @@ void manager_undo_generators(Manager *m) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
strv_remove(m->lookup_paths.unit_path, m->generator_unit_path);
|
strv_remove(m->lookup_paths.unit_path, m->generator_unit_path);
|
||||||
rm_rf(m->generator_unit_path, false, true);
|
rm_rf(m->generator_unit_path, false, true, false);
|
||||||
|
|
||||||
free(m->generator_unit_path);
|
free(m->generator_unit_path);
|
||||||
m->generator_unit_path = NULL;
|
m->generator_unit_path = NULL;
|
||||||
|
|
|
@ -586,7 +586,7 @@ static int remove_item(Item *i, const char *instance) {
|
||||||
|
|
||||||
case TRUNCATE_DIRECTORY:
|
case TRUNCATE_DIRECTORY:
|
||||||
case RECURSIVE_REMOVE_PATH:
|
case RECURSIVE_REMOVE_PATH:
|
||||||
if ((r = rm_rf(instance, false, i->type == RECURSIVE_REMOVE_PATH)) < 0 &&
|
if ((r = rm_rf(instance, false, i->type == RECURSIVE_REMOVE_PATH, false)) < 0 &&
|
||||||
r != -ENOENT) {
|
r != -ENOENT) {
|
||||||
log_error("rm_rf(%s): %s", instance, strerror(-r));
|
log_error("rm_rf(%s): %s", instance, strerror(-r));
|
||||||
return r;
|
return r;
|
||||||
|
|
60
src/util.c
60
src/util.c
|
@ -3354,7 +3354,7 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rm_rf_children(int fd, bool only_dirs) {
|
static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) {
|
||||||
DIR *d;
|
DIR *d;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -3371,7 +3371,7 @@ static int rm_rf_children(int fd, bool only_dirs) {
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct dirent buf, *de;
|
struct dirent buf, *de;
|
||||||
bool is_dir;
|
bool is_dir, keep_around = false;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = readdir_r(d, &buf, &de)) != 0) {
|
if ((r = readdir_r(d, &buf, &de)) != 0) {
|
||||||
|
@ -3395,9 +3395,26 @@ static int rm_rf_children(int fd, bool only_dirs) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (honour_sticky)
|
||||||
|
keep_around = st.st_uid == 0 && (st.st_mode & S_ISVTX);
|
||||||
|
|
||||||
is_dir = S_ISDIR(st.st_mode);
|
is_dir = S_ISDIR(st.st_mode);
|
||||||
} else
|
|
||||||
|
} else {
|
||||||
|
if (honour_sticky) {
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
|
||||||
|
if (ret == 0 && errno != ENOENT)
|
||||||
|
ret = -errno;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_around = st.st_uid == 0 && (st.st_mode & S_ISVTX);
|
||||||
|
}
|
||||||
|
|
||||||
is_dir = de->d_type == DT_DIR;
|
is_dir = de->d_type == DT_DIR;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_dir) {
|
if (is_dir) {
|
||||||
int subdir_fd;
|
int subdir_fd;
|
||||||
|
@ -3408,16 +3425,18 @@ static int rm_rf_children(int fd, bool only_dirs) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((r = rm_rf_children(subdir_fd, only_dirs)) < 0) {
|
if ((r = rm_rf_children(subdir_fd, only_dirs, honour_sticky)) < 0) {
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = r;
|
ret = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
|
if (!keep_around)
|
||||||
if (ret == 0 && errno != ENOENT)
|
if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
|
||||||
ret = -errno;
|
if (ret == 0 && errno != ENOENT)
|
||||||
}
|
ret = -errno;
|
||||||
} else if (!only_dirs) {
|
}
|
||||||
|
|
||||||
|
} else if (!only_dirs && !keep_around) {
|
||||||
|
|
||||||
if (unlinkat(fd, de->d_name, 0) < 0) {
|
if (unlinkat(fd, de->d_name, 0) < 0) {
|
||||||
if (ret == 0 && errno != ENOENT)
|
if (ret == 0 && errno != ENOENT)
|
||||||
|
@ -3431,7 +3450,7 @@ static int rm_rf_children(int fd, bool only_dirs) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rm_rf(const char *path, bool only_dirs, bool delete_root) {
|
int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
|
||||||
int fd;
|
int fd;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -3449,13 +3468,18 @@ int rm_rf(const char *path, bool only_dirs, bool delete_root) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = rm_rf_children(fd, only_dirs);
|
r = rm_rf_children(fd, only_dirs, honour_sticky);
|
||||||
|
|
||||||
|
if (delete_root) {
|
||||||
|
|
||||||
|
if (honour_sticky && file_is_sticky(path) > 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (delete_root)
|
|
||||||
if (rmdir(path) < 0) {
|
if (rmdir(path) < 0) {
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
r = -errno;
|
r = -errno;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -5674,6 +5698,18 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int file_is_sticky(const char *p) {
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
assert(p);
|
||||||
|
|
||||||
|
if (lstat(p, &st) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return
|
||||||
|
st.st_uid == 0 &&
|
||||||
|
(st.st_mode & S_ISVTX);
|
||||||
|
}
|
||||||
|
|
||||||
static const char *const ioprio_class_table[] = {
|
static const char *const ioprio_class_table[] = {
|
||||||
[IOPRIO_CLASS_NONE] = "none",
|
[IOPRIO_CLASS_NONE] = "none",
|
||||||
|
|
|
@ -362,7 +362,7 @@ int get_ctty(pid_t, dev_t *_devnr, char **r);
|
||||||
|
|
||||||
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
|
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
|
||||||
|
|
||||||
int rm_rf(const char *path, bool only_dirs, bool delete_root);
|
int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky);
|
||||||
|
|
||||||
int pipe_eof(int fd);
|
int pipe_eof(int fd);
|
||||||
|
|
||||||
|
@ -467,6 +467,8 @@ bool in_charset(const char *s, const char* charset);
|
||||||
|
|
||||||
int block_get_whole_disk(dev_t d, dev_t *ret);
|
int block_get_whole_disk(dev_t d, dev_t *ret);
|
||||||
|
|
||||||
|
int file_is_sticky(const char *p);
|
||||||
|
|
||||||
#define NULSTR_FOREACH(i, l) \
|
#define NULSTR_FOREACH(i, l) \
|
||||||
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
|
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue