user-util: add new helper fully_set_uid_gid()
Usually when we do setresuid() we also do setesgid() and setgroups(). Let's add a common helper that does all three, and use it everywhere.
This commit is contained in:
+14
-5
@@ -661,17 +661,26 @@ int get_shell(char **ret) {
|
||||
return path_simplify_alloc(e, ret);
|
||||
}
|
||||
|
||||
int reset_uid_gid(void) {
|
||||
int fully_set_uid_gid(uid_t uid, gid_t gid, const gid_t supplementary_gids[], size_t n_supplementary_gids) {
|
||||
int r;
|
||||
|
||||
r = maybe_setgroups(0, NULL);
|
||||
assert(supplementary_gids || n_supplementary_gids == 0);
|
||||
|
||||
/* Sets all UIDs and all GIDs to the specified ones. Drops all auxiliary GIDs */
|
||||
|
||||
r = maybe_setgroups(n_supplementary_gids, supplementary_gids);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (setresgid(0, 0, 0) < 0)
|
||||
return -errno;
|
||||
if (gid_is_valid(gid))
|
||||
if (setresgid(gid, gid, gid) < 0)
|
||||
return -errno;
|
||||
|
||||
return RET_NERRNO(setresuid(0, 0, 0));
|
||||
if (uid_is_valid(uid))
|
||||
if (setresuid(uid, uid, uid) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int take_etc_passwd_lock(const char *root) {
|
||||
|
||||
@@ -57,7 +57,10 @@ int getgroups_alloc(gid_t** gids);
|
||||
int get_home_dir(char **ret);
|
||||
int get_shell(char **ret);
|
||||
|
||||
int reset_uid_gid(void);
|
||||
int fully_set_uid_gid(uid_t uid, gid_t gid, const gid_t supplementary_gids[], size_t n_supplementary_gids);
|
||||
static inline int reset_uid_gid(void) {
|
||||
return fully_set_uid_gid(0, 0, NULL, 0);
|
||||
}
|
||||
|
||||
int take_etc_passwd_lock(const char *root);
|
||||
|
||||
|
||||
@@ -1220,13 +1220,9 @@ static int setup_pam(
|
||||
* PR_SET_PDEATHSIG work in most cases. If this fails, ignore the error - but expect sd-pam
|
||||
* threads to fail to exit normally */
|
||||
|
||||
r = maybe_setgroups(0, NULL);
|
||||
r = fully_set_uid_gid(uid, gid, /* supplementary_gids= */ NULL, /* n_supplementary_gids= */ 0);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to setgroups() in sd-pam: %m");
|
||||
if (setresgid(gid, gid, gid) < 0)
|
||||
log_warning_errno(errno, "Failed to setresgid() in sd-pam: %m");
|
||||
if (setresuid(uid, uid, uid) < 0)
|
||||
log_warning_errno(errno, "Failed to setresuid() in sd-pam: %m");
|
||||
log_warning_errno(r, "Failed to drop privileges in sd-pam: %m");
|
||||
|
||||
(void) ignore_signals(SIGPIPE);
|
||||
|
||||
|
||||
+3
-15
@@ -2085,23 +2085,11 @@ int home_killall(Home *h) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
gid_t gid;
|
||||
|
||||
/* Child */
|
||||
|
||||
gid = user_record_gid(h->record);
|
||||
if (setresgid(gid, gid, gid) < 0) {
|
||||
log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setgroups(0, NULL) < 0) {
|
||||
log_error_errno(errno, "Failed to reset auxiliary groups list: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setresuid(h->uid, h->uid, h->uid) < 0) {
|
||||
log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", h->uid);
|
||||
r = fully_set_uid_gid(h->uid, user_record_gid(h->record), /* supplementary_gids= */ NULL, /* n_supplementary_gids= */ 0);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to change UID/GID to " UID_FMT "/" GID_FMT ": %m", h->uid, user_record_gid(h->record));
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
@@ -319,23 +319,11 @@ int home_setup_fscrypt(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed install encryption key in user's keyring: %m");
|
||||
if (r == 0) {
|
||||
gid_t gid;
|
||||
|
||||
/* Child */
|
||||
|
||||
gid = user_record_gid(h);
|
||||
if (setresgid(gid, gid, gid) < 0) {
|
||||
log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setgroups(0, NULL) < 0) {
|
||||
log_error_errno(errno, "Failed to reset auxiliary groups list: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setresuid(h->uid, h->uid, h->uid) < 0) {
|
||||
log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", h->uid);
|
||||
r = fully_set_uid_gid(h->uid, user_record_gid(h), /* supplementary_gids= */ NULL, /* n_supplementary_gids= */ 0);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to change UID/GID to " UID_FMT "/" GID_FMT ": %m", h->uid, user_record_gid(h));
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ int change_uid_gid_raw(
|
||||
size_t n_supplementary_gids,
|
||||
bool chown_stdio) {
|
||||
|
||||
int r;
|
||||
|
||||
if (!uid_is_valid(uid))
|
||||
uid = 0;
|
||||
if (!gid_is_valid(gid))
|
||||
@@ -67,14 +69,9 @@ int change_uid_gid_raw(
|
||||
(void) fchown(STDERR_FILENO, uid, gid);
|
||||
}
|
||||
|
||||
if (setgroups(n_supplementary_gids, supplementary_gids) < 0)
|
||||
return log_error_errno(errno, "Failed to set auxiliary groups: %m");
|
||||
|
||||
if (setresgid(gid, gid, gid) < 0)
|
||||
return log_error_errno(errno, "setresgid() failed: %m");
|
||||
|
||||
if (setresuid(uid, uid, uid) < 0)
|
||||
return log_error_errno(errno, "setresuid() failed: %m");
|
||||
r = fully_set_uid_gid(uid, gid, supplementary_gids, n_supplementary_gids);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Changing privileges failed: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -176,10 +176,7 @@ TEST(getpeercred_getpeergroups) {
|
||||
test_gids = (gid_t*) gids;
|
||||
n_test_gids = ELEMENTSOF(gids);
|
||||
|
||||
assert_se(setgroups(n_test_gids, test_gids) >= 0);
|
||||
assert_se(setresgid(test_gid, test_gid, test_gid) >= 0);
|
||||
assert_se(setresuid(test_uid, test_uid, test_uid) >= 0);
|
||||
|
||||
assert_se(fully_set_uid_gid(test_uid, test_gid, test_gids, n_test_gids) >= 0);
|
||||
} else {
|
||||
long ngroups_max;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user