Skip to content

Commit a1cad43

Browse files
authored
Merge pull request systemd#22341 from poettering/pam-end-fix
pid1: pam_end() PAM_DATA_SILENT fix
2 parents 007e03b + 421bb42 commit a1cad43

File tree

1 file changed

+24
-30
lines changed

1 file changed

+24
-30
lines changed

src/core/execute.c

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,7 +1172,7 @@ static int setup_pam(
11721172
uid_t uid,
11731173
gid_t gid,
11741174
const char *tty,
1175-
char ***env,
1175+
char ***env, /* updated on success */
11761176
const int fds[], size_t n_fds) {
11771177

11781178
#if HAVE_PAM
@@ -1183,10 +1183,11 @@ static int setup_pam(
11831183
};
11841184

11851185
_cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
1186+
_cleanup_strv_free_ char **e = NULL;
11861187
pam_handle_t *handle = NULL;
11871188
sigset_t old_ss;
11881189
int pam_code = PAM_SUCCESS, r;
1189-
char **nv, **e = NULL;
1190+
char **nv;
11901191
bool close_session = false;
11911192
pid_t pam_pid = 0, parent_pid;
11921193
int flags = 0;
@@ -1257,8 +1258,7 @@ static int setup_pam(
12571258
goto fail;
12581259
}
12591260

1260-
/* Block SIGTERM, so that we know that it won't get lost in
1261-
* the child */
1261+
/* Block SIGTERM, so that we know that it won't get lost in the child */
12621262

12631263
assert_se(sigprocmask_many(SIG_BLOCK, &old_ss, SIGTERM, -1) >= 0);
12641264

@@ -1270,18 +1270,16 @@ static int setup_pam(
12701270
if (r == 0) {
12711271
int sig, ret = EXIT_PAM;
12721272

1273-
/* The child's job is to reset the PAM session on
1274-
* termination */
1273+
/* The child's job is to reset the PAM session on termination */
12751274
barrier_set_role(&barrier, BARRIER_CHILD);
12761275

12771276
/* Make sure we don't keep open the passed fds in this child. We assume that otherwise only
12781277
* those fds are open here that have been opened by PAM. */
12791278
(void) close_many(fds, n_fds);
12801279

1281-
/* Drop privileges - we don't need any to pam_close_session
1282-
* and this will make PR_SET_PDEATHSIG work in most cases.
1283-
* If this fails, ignore the error - but expect sd-pam threads
1284-
* to fail to exit normally */
1280+
/* Drop privileges - we don't need any to pam_close_session and this will make
1281+
* PR_SET_PDEATHSIG work in most cases. If this fails, ignore the error - but expect sd-pam
1282+
* threads to fail to exit normally */
12851283

12861284
r = maybe_setgroups(0, NULL);
12871285
if (r < 0)
@@ -1293,20 +1291,16 @@ static int setup_pam(
12931291

12941292
(void) ignore_signals(SIGPIPE);
12951293

1296-
/* Wait until our parent died. This will only work if
1297-
* the above setresuid() succeeds, otherwise the kernel
1298-
* will not allow unprivileged parents kill their privileged
1299-
* children this way. We rely on the control groups kill logic
1300-
* to do the rest for us. */
1294+
/* Wait until our parent died. This will only work if the above setresuid() succeeds,
1295+
* otherwise the kernel will not allow unprivileged parents kill their privileged children
1296+
* this way. We rely on the control groups kill logic to do the rest for us. */
13011297
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
13021298
goto child_finish;
13031299

1304-
/* Tell the parent that our setup is done. This is especially
1305-
* important regarding dropping privileges. Otherwise, unit
1306-
* setup might race against our setresuid(2) call.
1300+
/* Tell the parent that our setup is done. This is especially important regarding dropping
1301+
* privileges. Otherwise, unit setup might race against our setresuid(2) call.
13071302
*
1308-
* If the parent aborted, we'll detect this below, hence ignore
1309-
* return failure here. */
1303+
* If the parent aborted, we'll detect this below, hence ignore return failure here. */
13101304
(void) barrier_place(&barrier);
13111305

13121306
/* Check if our parent process might already have died? */
@@ -1343,25 +1337,27 @@ static int setup_pam(
13431337
ret = 0;
13441338

13451339
child_finish:
1346-
pam_end(handle, pam_code | flags);
1340+
/* NB: pam_end() when called in child processes should set PAM_DATA_SILENT to let the module
1341+
* know about this. See pam_end(3) */
1342+
(void) pam_end(handle, pam_code | flags | PAM_DATA_SILENT);
13471343
_exit(ret);
13481344
}
13491345

13501346
barrier_set_role(&barrier, BARRIER_PARENT);
13511347

1352-
/* If the child was forked off successfully it will do all the
1353-
* cleanups, so forget about the handle here. */
1348+
/* If the child was forked off successfully it will do all the cleanups, so forget about the handle
1349+
* here. */
13541350
handle = NULL;
13551351

13561352
/* Unblock SIGTERM again in the parent */
13571353
assert_se(sigprocmask(SIG_SETMASK, &old_ss, NULL) >= 0);
13581354

1359-
/* We close the log explicitly here, since the PAM modules
1360-
* might have opened it, but we don't want this fd around. */
1355+
/* We close the log explicitly here, since the PAM modules might have opened it, but we don't want
1356+
* this fd around. */
13611357
closelog();
13621358

1363-
/* Synchronously wait for the child to initialize. We don't care for
1364-
* errors as we cannot recover. However, warn loudly if it happens. */
1359+
/* Synchronously wait for the child to initialize. We don't care for errors as we cannot
1360+
* recover. However, warn loudly if it happens. */
13651361
if (!barrier_place_and_sync(&barrier))
13661362
log_error("PAM initialization failed");
13671363

@@ -1378,12 +1374,10 @@ static int setup_pam(
13781374
if (close_session)
13791375
pam_code = pam_close_session(handle, flags);
13801376

1381-
pam_end(handle, pam_code | flags);
1377+
(void) pam_end(handle, pam_code | flags);
13821378
}
13831379

1384-
strv_free(e);
13851380
closelog();
1386-
13871381
return r;
13881382
#else
13891383
return 0;

0 commit comments

Comments
 (0)