Make PrivateTmp dirs also inaccessible from the outside

Currently, PrivateTmp=yes means that the service cannot see the /tmp
shared by rest of the system and is isolated from other services using
PrivateTmp, but users can access and modify /tmp as seen by the
service.

Move the private /tmp and /var/tmp directories into a 0077-mode
directory. This way unpriviledged users on the system cannot see (or
modify) /tmp as seen by the service.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2013-03-20 01:38:28 -04:00
parent 1f048a6b6b
commit d34cd37490
5 changed files with 54 additions and 47 deletions

View file

@ -40,6 +40,7 @@
#include <sys/poll.h> #include <sys/poll.h>
#include <linux/seccomp-bpf.h> #include <linux/seccomp-bpf.h>
#include <glob.h> #include <glob.h>
#include <libgen.h>
#ifdef HAVE_PAM #ifdef HAVE_PAM
#include <security/pam_appl.h> #include <security/pam_appl.h>
@ -1551,19 +1552,22 @@ void exec_context_init(ExecContext *c) {
} }
void exec_context_tmp_dirs_done(ExecContext *c) { void exec_context_tmp_dirs_done(ExecContext *c) {
assert(c); char* dirs[] = {c->tmp_dir ? c->tmp_dir : c->var_tmp_dir,
c->tmp_dir ? c->var_tmp_dir : NULL,
NULL};
char **dirp;
if (c->tmp_dir) { for(dirp = dirs; *dirp; dirp++) {
rm_rf_dangerous(c->tmp_dir, false, true, false); char *dir;
free(c->tmp_dir); rm_rf_dangerous(*dirp, false, true, false);
c->tmp_dir = NULL;
dir = dirname(*dirp);
rmdir(dir);
free(*dirp);
} }
if (c->var_tmp_dir) { c->tmp_dir = c->var_tmp_dir = NULL;
rm_rf_dangerous(c->var_tmp_dir, false, true, false);
free(c->var_tmp_dir);
c->var_tmp_dir = NULL;
}
} }
void exec_context_done(ExecContext *c, bool reloading_or_reexecuting) { void exec_context_done(ExecContext *c, bool reloading_or_reexecuting) {

View file

@ -183,22 +183,20 @@ int setup_tmpdirs(char **tmp_dir,
assert(tmp_dir); assert(tmp_dir);
assert(var_tmp_dir); assert(var_tmp_dir);
r = create_tmp_dir(tmp_dir_template, 0000, true, tmp_dir); r = create_tmp_dir(tmp_dir_template, tmp_dir);
if (r < 0) if (r < 0)
goto fail2; return r;
r = create_tmp_dir(var_tmp_dir_template, 0000, true, var_tmp_dir); r = create_tmp_dir(var_tmp_dir_template, var_tmp_dir);
if (r < 0) if (r == 0)
goto fail1; return 0;
return 0; /* failure */
fail1:
rmdir(*tmp_dir); rmdir(*tmp_dir);
rmdir(tmp_dir_template);
free(*tmp_dir); free(*tmp_dir);
*tmp_dir = NULL; *tmp_dir = NULL;
fail2:
return r; return r;
} }

View file

@ -5683,46 +5683,49 @@ int search_and_fopen_nulstr(const char *path, const char *mode, const char *sear
return search_and_fopen_internal(path, mode, s, _f); return search_and_fopen_internal(path, mode, s, _f);
} }
int create_tmp_dir(char template[], mode_t mask, bool need_sticky, char** dir_name) { int create_tmp_dir(char template[], char** dir_name) {
int r = 0; int r = 0;
char *d = NULL; char *d, *dt;
bool remove = false;
mode_t _cleanup_umask_ u; mode_t _cleanup_umask_ u;
assert(dir_name); assert(dir_name);
u = umask(mask); u = umask(0077);
d = mkdtemp(template); d = mkdtemp(template);
if (!d) { if (!d) {
r = -errno; log_error("Can't create directory %s: %m", template);
log_debug("Can't create directory"); return -errno;
goto fail;
} }
remove = true; dt = strjoin(d, "/tmp", NULL);
if (!dt) {
log_debug("Created temporary directory : %s", template);
d = strdup(template);
if (!d) {
r = log_oom(); r = log_oom();
goto fail; goto fail2;
} }
if (need_sticky) { umask(0000);
r = chmod(template, 0777 | S_ISVTX); r = mkdir(dt, 0777);
if (r < 0) { if (r) {
r = -errno; log_error("Can't create directory %s: %m", dt);
goto fail; r = -errno;
} goto fail1;
log_debug("Setting sticky bit on : %s", template);
} }
log_debug("Created temporary directory %s", dt);
*dir_name = d; r = chmod(dt, 0777 | S_ISVTX);
if (r < 0) {
log_error("Failed to chmod %s: %m", dt);
r = -errno;
goto fail1;
}
log_debug("Set sticky bit on %s", dt);
*dir_name = dt;
return 0; return 0;
fail: fail1:
if (remove) rmdir(dt);
rmdir(template); fail2:
rmdir(template);
return r; return r;
} }

View file

@ -579,7 +579,7 @@ int on_ac_power(void);
int search_and_fopen(const char *path, const char *mode, const char **search, FILE **_f); int search_and_fopen(const char *path, const char *mode, const char **search, FILE **_f);
int search_and_fopen_nulstr(const char *path, const char *mode, const char *search, FILE **_f); int search_and_fopen_nulstr(const char *path, const char *mode, const char *search, FILE **_f);
int create_tmp_dir(char template[], mode_t mask, bool need_sticky, char** dir_name); int create_tmp_dir(char template[], char** dir_name);
#define FOREACH_LINE(line, f, on_error) \ #define FOREACH_LINE(line, f, on_error) \
for (;;) \ for (;;) \

View file

@ -12,5 +12,7 @@ d /tmp 1777 root root 10d
d /var/tmp 1777 root root 30d d /var/tmp 1777 root root 30d
# Exclude namespace mountpoints created with PrivateTmp=yes # Exclude namespace mountpoints created with PrivateTmp=yes
X /tmp/systemd-private-* x /tmp/systemd-private-*
X /var/tmp/systemd-private-* x /var/tmp/systemd-private-*
X /tmp/systemd-private-*/tmp
X /var/tmp/systemd-private-*/tmp