Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
Already on GitHub? Sign in to your account
Fix creation of $XDG_RUNTIME_DIR and $SNAP_USER_DATA #195
b2f5002
adfcce5
9f9371b
d0d3074
61df233
dedf855
| @@ -113,6 +113,11 @@ int main(int argc, char **argv) | ||
| setup_devices_cgroup(security_tag, &udev_s); | ||
| snappy_udev_cleanup(&udev_s); | ||
| + // Setup the XDG_RUNTIME_DIR as root (we need to write to /run here) | ||
| + setup_user_xdg_runtime_dir(real_uid, real_gid); | ||
| + // Ensure that the user data path exists. | ||
| + setup_user_data(real_uid, real_gid); | ||
| + | ||
jdstrand
Contributor
|
||
| // The rest does not so temporarily drop privs back to calling | ||
| // user (we'll permanently drop after loading seccomp) | ||
| if (setegid(real_gid) != 0) | ||
| @@ -125,10 +130,6 @@ int main(int argc, char **argv) | ||
| if (real_uid != 0 && getegid() == 0) | ||
| die("dropping privs did not work"); | ||
| } | ||
| - // Ensure that the user data path exists. | ||
| - setup_user_data(); | ||
| - setup_user_xdg_runtime_dir(); | ||
| - | ||
| // https://wiki.ubuntu.com/SecurityTeam/Specifications/SnappyConfinement | ||
| #ifdef HAVE_APPARMOR | ||
| int rc = 0; | ||
| @@ -17,49 +17,120 @@ | ||
| #include "config.h" | ||
| #include "user-support.h" | ||
| -#include <errno.h> | ||
| #include <stdlib.h> | ||
| #include <sys/stat.h> | ||
| +#include <unistd.h> | ||
| #include "utils.h" | ||
| -void setup_user_data() | ||
| +void setup_user_data(uid_t uid, gid_t gid) | ||
| { | ||
| const char *user_data = getenv("SNAP_USER_DATA"); | ||
| - | ||
| if (user_data == NULL) | ||
| return; | ||
| - | ||
| // Only support absolute paths. | ||
| if (user_data[0] != '/') { | ||
| die("user data directory must be an absolute path"); | ||
| } | ||
| - | ||
| + // Describe how the created directory should look like. | ||
| + int hint_SNAP_USER_DATA(int depth, const char *segment, | ||
| + mode_t * mode_p, uid_t * uid_p, gid_t * gid_p) { | ||
| + switch (depth) { | ||
| + case 0: | ||
| + // That's / | ||
| + break; | ||
| + case 1: | ||
| + // that's /home | ||
| + break; | ||
| + case 2: | ||
| + /// that's /home/$LOGNAME | ||
| + break; | ||
| + case 3: | ||
| + // that's /home/$LOGNAME/snap | ||
| + // NOTE: fall-through | ||
| + case 4: | ||
| + // that's /home/$LOGNAME/snap/$SNAP_NAME | ||
| + // NOTE: fall-through | ||
| + case 5: | ||
| + // that's /home/$LOGNAME/snap/$SNAP_NAME/$SNAP_REVISION | ||
| + *uid_p = uid; | ||
| + *gid_p = gid; | ||
| + *mode_p = 0755; | ||
| + break; | ||
| + default: | ||
| + die("unexpected SNAP_USER_DATA segment: %s at depth %d", | ||
| + segment, depth); | ||
| + } | ||
| + return 0; | ||
| + } | ||
jdstrand
Contributor
|
||
| + struct sc_mkpath_opts opts = { | ||
| + .mode = 0755, | ||
| + .uid = uid, | ||
| + .gid = gid, | ||
| + .hint_fn = hint_SNAP_USER_DATA, | ||
| + .do_chown = true, | ||
| + }; | ||
| debug("creating user data directory: %s", user_data); | ||
| - if (sc_nonfatal_mkpath(user_data, 0755) < 0) { | ||
| + if (sc_nonfatal_mkpath(user_data, &opts) < 0) { | ||
| die("cannot create user data directory: %s", user_data); | ||
| }; | ||
| } | ||
| -void setup_user_xdg_runtime_dir() | ||
| +void setup_user_xdg_runtime_dir(uid_t uid, gid_t gid) | ||
| { | ||
| + debug("considering creating $XDG_RUNTIME_DIR for the snap session"); | ||
| const char *xdg_runtime_dir = getenv("XDG_RUNTIME_DIR"); | ||
| - | ||
| - if (xdg_runtime_dir == NULL) | ||
| + debug("XDG_RUNTIME_DIR is %s", xdg_runtime_dir); | ||
| + if (xdg_runtime_dir == NULL) { | ||
| + debug("XDG_RUNTIME_DIR is not set"); | ||
| return; | ||
| + } | ||
| // Only support absolute paths. | ||
| if (xdg_runtime_dir[0] != '/') { | ||
| die("XDG_RUNTIME_DIR must be an absolute path"); | ||
| } | ||
| - errno = 0; | ||
| + int hint_XDG_RUNTIME_DIR(int depth, const char *segment, | ||
| + mode_t * mode_p, uid_t * uid_p, | ||
| + gid_t * gid_p) { | ||
| + switch (depth) { | ||
| + case 0: | ||
| + // That's / | ||
| + break; | ||
| + case 1: | ||
| + // That's /run | ||
| + *uid_p = 0; | ||
| + *gid_p = 0; | ||
| + break; | ||
| + case 2: | ||
| + // That's /run/user | ||
| + break; | ||
| + case 3: | ||
| + // That's /run/user/user/$(id -u) | ||
| + *uid_p = uid; | ||
| + *gid_p = gid; | ||
| + *mode_p = 0700; | ||
| + break; | ||
| + case 4: | ||
| + // That's /run/user/$(id -u)/snap.$SNAP_NAME | ||
| + *uid_p = uid; | ||
| + *gid_p = gid; | ||
| + break; | ||
| + default: | ||
| + die("unexpected XDR_RUNTIME_DIR segment: %s at depth %d", segment, depth); | ||
| + } | ||
| + return 0; | ||
| + } | ||
| + struct sc_mkpath_opts opts = { | ||
| + .mode = 0755, | ||
| + .uid = uid, | ||
| + .gid = gid, | ||
| + .hint_fn = hint_XDG_RUNTIME_DIR, | ||
| + .do_chown = true, | ||
| + }; | ||
jdstrand
Contributor
|
||
| debug("creating user XDG_RUNTIME_DIR directory: %s", xdg_runtime_dir); | ||
| - if (sc_nonfatal_mkpath(xdg_runtime_dir, 0755) < 0) { | ||
| + if (sc_nonfatal_mkpath(xdg_runtime_dir, &opts) < 0) { | ||
| die("cannot create user XDG_RUNTIME_DIR directory: %s", | ||
| xdg_runtime_dir); | ||
| } | ||
| - // if successfully created the directory (ie, not EEXIST), then chmod it. | ||
| - if (errno == 0 && chmod(xdg_runtime_dir, 0700) != 0) { | ||
| - die("cannot change permissions of user XDG_RUNTIME_DIR directory to 0700"); | ||
| - } | ||
| } | ||
This one needs to be 700. The spec says XDG_RUNTIME_DIR needs to be 700. XDG_RUNTIME_DIR for the snap is set to
/run/user/$(id -u test)/snap.nameand there might be software that verifies this.