int sc_lock(const char *scope) { // Create (if required) and open the lock directory. debug("creating lock directory %s (if missing)", sc_lock_dir); if (sc_nonfatal_mkpath(sc_lock_dir, 0755) < 0) { die("cannot create lock directory %s", sc_lock_dir); } debug("opening lock directory %s", sc_lock_dir); int dir_fd SC_CLEANUP(sc_cleanup_close) = -1; dir_fd = open(sc_lock_dir, O_DIRECTORY | O_PATH | O_CLOEXEC | O_NOFOLLOW); if (dir_fd < 0) { die("cannot open lock directory"); } // Construct the name of the lock file. char lock_fname[PATH_MAX]; sc_must_snprintf(lock_fname, sizeof lock_fname, "%s/%s.lock", sc_lock_dir, scope ? : ""); // Open the lock file and acquire an exclusive lock. debug("opening lock file: %s", lock_fname); int lock_fd = openat(dir_fd, lock_fname, O_CREAT | O_RDWR | O_CLOEXEC | O_NOFOLLOW, 0600); if (lock_fd < 0) { die("cannot open lock file: %s", lock_fname); } sc_enable_sanity_timeout(); debug("acquiring exclusive lock (scope %s)", scope ? : "(global)"); if (flock(lock_fd, LOCK_EX) < 0) { sc_disable_sanity_timeout(); close(lock_fd); die("cannot acquire exclusive lock (scope %s)", scope ? : "(global)"); } else {
/** * Create an empty directory and bind mount something there. * * The empty directory is created at destdir. The bind mount is * done from srcdir to destdir. The bind mount is performed with * caller-defined flags. **/ static void sc_quirk_mkdir_bind(const char *src_dir, const char *dest_dir, unsigned flags) { flags |= MS_BIND; debug("creating empty directory at %s", dest_dir); if (sc_nonfatal_mkpath(dest_dir, 0755) < 0) { die("cannot create empty directory at %s", dest_dir); } const char *flags_str = sc_mount_opt2str(flags); debug("performing operation: mount %s %s -o %s", src_dir, dest_dir, flags_str); if (mount(src_dir, dest_dir, NULL, flags, NULL) != 0) { die("cannot perform operation: mount %s %s -o %s", src_dir, dest_dir, flags_str); } }
void sc_initialize_ns_groups() { debug("creating namespace group directory %s", sc_ns_dir); if (sc_nonfatal_mkpath(sc_ns_dir, 0755) < 0) { die("cannot create namespace group directory %s", sc_ns_dir); } debug("opening namespace group directory %s", sc_ns_dir); int dir_fd __attribute__ ((cleanup(sc_cleanup_close))) = -1; dir_fd = open(sc_ns_dir, O_DIRECTORY | O_PATH | O_CLOEXEC | O_NOFOLLOW); if (dir_fd < 0) { die("cannot open namespace group directory"); } debug("opening lock file for group directory"); int lock_fd __attribute__ ((cleanup(sc_cleanup_close))) = -1; lock_fd = openat(dir_fd, SC_NS_LOCK_FILE, O_CREAT | O_RDWR | O_CLOEXEC | O_NOFOLLOW, 0600); if (lock_fd < 0) { die("cannot open lock file for namespace group directory"); } debug("locking the namespace group directory"); sc_enable_sanity_timeout(); if (flock(lock_fd, LOCK_EX) < 0) { die("cannot acquire exclusive lock for namespace group directory"); } sc_disable_sanity_timeout(); if (!sc_is_ns_group_dir_private()) { debug ("bind mounting the namespace group directory over itself"); if (mount(sc_ns_dir, sc_ns_dir, NULL, MS_BIND | MS_REC, NULL) < 0) { die("cannot bind mount namespace group directory over itself"); } debug ("making the namespace group directory mount point private"); if (mount(NULL, sc_ns_dir, NULL, MS_PRIVATE, NULL) < 0) { die("cannot make the namespace group directory mount point private"); } } else { debug ("namespace group directory does not require intialization"); } debug("unlocking the namespace group directory"); if (flock(lock_fd, LOCK_UN) < 0) { die("cannot release lock for namespace control directory"); } }
void setup_user_data(void) { 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"); } debug("creating user data directory: %s", user_data); if (sc_nonfatal_mkpath(user_data, 0755) < 0) { die("cannot create user data directory: %s", user_data); }; }
void setup_user_xdg_runtime_dir(void) { const char *xdg_runtime_dir = getenv("XDG_RUNTIME_DIR"); if (xdg_runtime_dir == NULL) return; // Only support absolute paths. if (xdg_runtime_dir[0] != '/') { die("XDG_RUNTIME_DIR must be an absolute path"); } errno = 0; debug("creating user XDG_RUNTIME_DIR directory: %s", xdg_runtime_dir); if (sc_nonfatal_mkpath(xdg_runtime_dir, 0755) < 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"); } }
void sc_initialize_ns_groups(void) { debug("creating namespace group directory %s", sc_ns_dir); if (sc_nonfatal_mkpath(sc_ns_dir, 0755) < 0) { die("cannot create namespace group directory %s", sc_ns_dir); } if (!sc_is_ns_group_dir_private()) { debug ("bind mounting the namespace group directory over itself"); if (mount(sc_ns_dir, sc_ns_dir, NULL, MS_BIND | MS_REC, NULL) < 0) { die("cannot bind mount namespace group directory over itself"); } debug ("making the namespace group directory mount point private"); if (mount(NULL, sc_ns_dir, NULL, MS_PRIVATE, NULL) < 0) { die("cannot make the namespace group directory mount point private"); } } else { debug ("namespace group directory does not require intialization"); } }