From: Luca Boccassi Date: Mon, 15 Jun 2020 14:36:00 +0000 (+0100) Subject: basic/mkdir: introduce safe recursive variants X-Git-Tag: v246-rc1~4^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=17b99e377be493b557934740807c2b2679aa23f3;p=thirdparty%2Fsystemd.git basic/mkdir: introduce safe recursive variants Add mkdir_p_safe and mkdir_parents_safe. Will be used by nspawn. --- diff --git a/src/basic/mkdir-label.c b/src/basic/mkdir-label.c index 0eba7fc514b..e844a598060 100644 --- a/src/basic/mkdir-label.c +++ b/src/basic/mkdir-label.c @@ -10,6 +10,7 @@ #include "mkdir.h" #include "selinux-util.h" #include "smack-util.h" +#include "user-util.h" int mkdir_label(const char *path, mode_t mode) { int r; @@ -50,9 +51,9 @@ int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirF } int mkdir_parents_label(const char *path, mode_t mode) { - return mkdir_parents_internal(NULL, path, mode, mkdir_label); + return mkdir_parents_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdir_label); } int mkdir_p_label(const char *path, mode_t mode) { - return mkdir_p_internal(NULL, path, mode, mkdir_label); + return mkdir_p_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdir_label); } diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c index ff20cec9858..ed5c4546e40 100644 --- a/src/basic/mkdir.c +++ b/src/basic/mkdir.c @@ -93,7 +93,7 @@ int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags f return mkdir_safe_internal(path, mode, uid, gid, flags, mkdir_errno_wrapper); } -int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) { +int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir) { const char *p, *e; int r; @@ -136,34 +136,54 @@ int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mk if (prefix && path_startswith(prefix, t)) continue; - r = _mkdir(t, mode); - if (r < 0 && r != -EEXIST) - return r; + if (uid == UID_INVALID && gid == UID_INVALID && flags == 0) { + r = _mkdir(t, mode); + if (r < 0 && r != -EEXIST) + return r; + } else { + r = mkdir_safe_internal(t, mode, uid, gid, flags, _mkdir); + if (r < 0 && r != -EEXIST) + return r; + } } } int mkdir_parents(const char *path, mode_t mode) { - return mkdir_parents_internal(NULL, path, mode, mkdir_errno_wrapper); + return mkdir_parents_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdir_errno_wrapper); +} + +int mkdir_parents_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) { + return mkdir_parents_internal(prefix, path, mode, uid, gid, flags, mkdir_errno_wrapper); } -int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) { +int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir) { int r; /* Like mkdir -p */ assert(_mkdir != mkdir); - r = mkdir_parents_internal(prefix, path, mode, _mkdir); + r = mkdir_parents_internal(prefix, path, mode, uid, gid, flags, _mkdir); if (r < 0) return r; - r = _mkdir(path, mode); - if (r < 0 && (r != -EEXIST || is_dir(path, true) <= 0)) - return r; + if (uid == UID_INVALID && gid == UID_INVALID && flags == 0) { + r = _mkdir(path, mode); + if (r < 0 && (r != -EEXIST || is_dir(path, true) <= 0)) + return r; + } else { + r = mkdir_safe_internal(path, mode, uid, gid, flags, _mkdir); + if (r < 0 && r != -EEXIST) + return r; + } return 0; } int mkdir_p(const char *path, mode_t mode) { - return mkdir_p_internal(NULL, path, mode, mkdir_errno_wrapper); + return mkdir_p_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdir_errno_wrapper); +} + +int mkdir_p_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) { + return mkdir_p_internal(prefix, path, mode, uid, gid, flags, mkdir_errno_wrapper); } diff --git a/src/basic/mkdir.h b/src/basic/mkdir.h index eb54853ea78..8bfaaf405bc 100644 --- a/src/basic/mkdir.h +++ b/src/basic/mkdir.h @@ -12,15 +12,17 @@ int mkdir_errno_wrapper(const char *pathname, mode_t mode); int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode); int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags); int mkdir_parents(const char *path, mode_t mode); +int mkdir_parents_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags); int mkdir_p(const char *path, mode_t mode); +int mkdir_p_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags); /* mandatory access control(MAC) versions */ int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags); -int mkdir_parents_label(const char *path, mode_t mode); +int mkdir_parents_label(const char *path, mode_t mod); int mkdir_p_label(const char *path, mode_t mode); /* internally used */ typedef int (*mkdir_func_t)(const char *pathname, mode_t mode); int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir); -int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir); -int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir); +int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir); +int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir);