Skip to content

Commit c8e00cd

Browse files
committed
Merge patch series "credential guards: credential preparation"
Christian Brauner <brauner@kernel.org> says: This converts most users combining * prepare_creds() * modify new creds * override_creds() * revert_creds() * put_cred() to rely on credentials guards. * patches from https://patch.msgid.link/20251103-work-creds-guards-prepare_creds-v1-0-b447b82f2c9b@kernel.org: trace: use override credential guard trace: use prepare credential guard coredump: use override credential guard coredump: use prepare credential guard coredump: split out do_coredump() from vfs_coredump() coredump: mark struct mm_struct as const coredump: pass struct linux_binfmt as const coredump: move revert_cred() before coredump_cleanup() sev-dev: use override credential guards sev-dev: use prepare credential guard sev-dev: use guard for path cred: add prepare credential guard Link: https://patch.msgid.link/20251103-work-creds-guards-prepare_creds-v1-0-b447b82f2c9b@kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org>
2 parents a857879 + 06765b6 commit c8e00cd

5 files changed

Lines changed: 88 additions & 100 deletions

File tree

drivers/crypto/ccp/sev-dev.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -259,27 +259,20 @@ static int sev_cmd_buffer_len(int cmd)
259259

260260
static struct file *open_file_as_root(const char *filename, int flags, umode_t mode)
261261
{
262-
struct file *fp;
263-
struct path root;
264-
struct cred *cred;
265-
const struct cred *old_cred;
262+
struct path root __free(path_put) = {};
266263

267264
task_lock(&init_task);
268265
get_fs_root(init_task.fs, &root);
269266
task_unlock(&init_task);
270267

271-
cred = prepare_creds();
268+
CLASS(prepare_creds, cred)();
272269
if (!cred)
273270
return ERR_PTR(-ENOMEM);
274-
cred->fsuid = GLOBAL_ROOT_UID;
275-
old_cred = override_creds(cred);
276271

277-
fp = file_open_root(&root, filename, flags, mode);
278-
path_put(&root);
279-
280-
put_cred(revert_creds(old_cred));
272+
cred->fsuid = GLOBAL_ROOT_UID;
281273

282-
return fp;
274+
scoped_with_creds(cred)
275+
return file_open_root(&root, filename, flags, mode);
283276
}
284277

285278
static int sev_read_init_ex_file(void)

fs/coredump.c

Lines changed: 71 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,7 +1036,7 @@ static bool coredump_pipe(struct core_name *cn, struct coredump_params *cprm,
10361036

10371037
static bool coredump_write(struct core_name *cn,
10381038
struct coredump_params *cprm,
1039-
struct linux_binfmt *binfmt)
1039+
const struct linux_binfmt *binfmt)
10401040
{
10411041

10421042
if (dump_interrupted())
@@ -1086,119 +1086,119 @@ static inline bool coredump_skip(const struct coredump_params *cprm,
10861086
return false;
10871087
}
10881088

1089-
void vfs_coredump(const kernel_siginfo_t *siginfo)
1089+
static void do_coredump(struct core_name *cn, struct coredump_params *cprm,
1090+
size_t **argv, int *argc, const struct linux_binfmt *binfmt)
10901091
{
1091-
struct cred *cred __free(put_cred) = NULL;
1092-
size_t *argv __free(kfree) = NULL;
1093-
struct core_state core_state;
1094-
struct core_name cn;
1095-
struct mm_struct *mm = current->mm;
1096-
struct linux_binfmt *binfmt = mm->binfmt;
1097-
const struct cred *old_cred;
1098-
int argc = 0;
1099-
struct coredump_params cprm = {
1100-
.siginfo = siginfo,
1101-
.limit = rlimit(RLIMIT_CORE),
1102-
/*
1103-
* We must use the same mm->flags while dumping core to avoid
1104-
* inconsistency of bit flags, since this flag is not protected
1105-
* by any locks.
1106-
*
1107-
* Note that we only care about MMF_DUMP* flags.
1108-
*/
1109-
.mm_flags = __mm_flags_get_dumpable(mm),
1110-
.vma_meta = NULL,
1111-
.cpu = raw_smp_processor_id(),
1112-
};
1113-
1114-
audit_core_dumps(siginfo->si_signo);
1115-
1116-
if (coredump_skip(&cprm, binfmt))
1117-
return;
1118-
1119-
cred = prepare_creds();
1120-
if (!cred)
1121-
return;
1122-
/*
1123-
* We cannot trust fsuid as being the "true" uid of the process
1124-
* nor do we know its entire history. We only know it was tainted
1125-
* so we dump it as root in mode 2, and only into a controlled
1126-
* environment (pipe handler or fully qualified path).
1127-
*/
1128-
if (coredump_force_suid_safe(&cprm))
1129-
cred->fsuid = GLOBAL_ROOT_UID;
1130-
1131-
if (coredump_wait(siginfo->si_signo, &core_state) < 0)
1132-
return;
1133-
1134-
old_cred = override_creds(cred);
1135-
1136-
if (!coredump_parse(&cn, &cprm, &argv, &argc)) {
1092+
if (!coredump_parse(cn, cprm, argv, argc)) {
11371093
coredump_report_failure("format_corename failed, aborting core");
1138-
goto close_fail;
1094+
return;
11391095
}
11401096

1141-
switch (cn.core_type) {
1097+
switch (cn->core_type) {
11421098
case COREDUMP_FILE:
1143-
if (!coredump_file(&cn, &cprm, binfmt))
1144-
goto close_fail;
1099+
if (!coredump_file(cn, cprm, binfmt))
1100+
return;
11451101
break;
11461102
case COREDUMP_PIPE:
1147-
if (!coredump_pipe(&cn, &cprm, argv, argc))
1148-
goto close_fail;
1103+
if (!coredump_pipe(cn, cprm, *argv, *argc))
1104+
return;
11491105
break;
11501106
case COREDUMP_SOCK_REQ:
11511107
fallthrough;
11521108
case COREDUMP_SOCK:
1153-
if (!coredump_socket(&cn, &cprm))
1154-
goto close_fail;
1109+
if (!coredump_socket(cn, cprm))
1110+
return;
11551111
break;
11561112
default:
11571113
WARN_ON_ONCE(true);
1158-
goto close_fail;
1114+
return;
11591115
}
11601116

11611117
/* Don't even generate the coredump. */
1162-
if (cn.mask & COREDUMP_REJECT)
1163-
goto close_fail;
1118+
if (cn->mask & COREDUMP_REJECT)
1119+
return;
11641120

11651121
/* get us an unshared descriptor table; almost always a no-op */
11661122
/* The cell spufs coredump code reads the file descriptor tables */
11671123
if (unshare_files())
1168-
goto close_fail;
1124+
return;
11691125

1170-
if ((cn.mask & COREDUMP_KERNEL) && !coredump_write(&cn, &cprm, binfmt))
1171-
goto close_fail;
1126+
if ((cn->mask & COREDUMP_KERNEL) && !coredump_write(cn, cprm, binfmt))
1127+
return;
11721128

1173-
coredump_sock_shutdown(cprm.file);
1129+
coredump_sock_shutdown(cprm->file);
11741130

11751131
/* Let the parent know that a coredump was generated. */
1176-
if (cn.mask & COREDUMP_USERSPACE)
1177-
cn.core_dumped = true;
1132+
if (cn->mask & COREDUMP_USERSPACE)
1133+
cn->core_dumped = true;
11781134

11791135
/*
11801136
* When core_pipe_limit is set we wait for the coredump server
11811137
* or usermodehelper to finish before exiting so it can e.g.,
11821138
* inspect /proc/<pid>.
11831139
*/
1184-
if (cn.mask & COREDUMP_WAIT) {
1185-
switch (cn.core_type) {
1140+
if (cn->mask & COREDUMP_WAIT) {
1141+
switch (cn->core_type) {
11861142
case COREDUMP_PIPE:
1187-
wait_for_dump_helpers(cprm.file);
1143+
wait_for_dump_helpers(cprm->file);
11881144
break;
11891145
case COREDUMP_SOCK_REQ:
11901146
fallthrough;
11911147
case COREDUMP_SOCK:
1192-
coredump_sock_wait(cprm.file);
1148+
coredump_sock_wait(cprm->file);
11931149
break;
11941150
default:
11951151
break;
11961152
}
11971153
}
1154+
}
1155+
1156+
void vfs_coredump(const kernel_siginfo_t *siginfo)
1157+
{
1158+
size_t *argv __free(kfree) = NULL;
1159+
struct core_state core_state;
1160+
struct core_name cn;
1161+
const struct mm_struct *mm = current->mm;
1162+
const struct linux_binfmt *binfmt = mm->binfmt;
1163+
int argc = 0;
1164+
struct coredump_params cprm = {
1165+
.siginfo = siginfo,
1166+
.limit = rlimit(RLIMIT_CORE),
1167+
/*
1168+
* We must use the same mm->flags while dumping core to avoid
1169+
* inconsistency of bit flags, since this flag is not protected
1170+
* by any locks.
1171+
*
1172+
* Note that we only care about MMF_DUMP* flags.
1173+
*/
1174+
.mm_flags = __mm_flags_get_dumpable(mm),
1175+
.vma_meta = NULL,
1176+
.cpu = raw_smp_processor_id(),
1177+
};
1178+
1179+
audit_core_dumps(siginfo->si_signo);
1180+
1181+
if (coredump_skip(&cprm, binfmt))
1182+
return;
1183+
1184+
CLASS(prepare_creds, cred)();
1185+
if (!cred)
1186+
return;
1187+
/*
1188+
* We cannot trust fsuid as being the "true" uid of the process
1189+
* nor do we know its entire history. We only know it was tainted
1190+
* so we dump it as root in mode 2, and only into a controlled
1191+
* environment (pipe handler or fully qualified path).
1192+
*/
1193+
if (coredump_force_suid_safe(&cprm))
1194+
cred->fsuid = GLOBAL_ROOT_UID;
1195+
1196+
if (coredump_wait(siginfo->si_signo, &core_state) < 0)
1197+
return;
11981198

1199-
close_fail:
1199+
scoped_with_creds(cred)
1200+
do_coredump(&cn, &cprm, &argv, &argc, binfmt);
12001201
coredump_cleanup(&cn, &cprm);
1201-
revert_creds(old_cred);
12021202
return;
12031203
}
12041204

include/linux/cred.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,11 @@ static inline void put_cred(const struct cred *cred)
280280
put_cred_many(cred, 1);
281281
}
282282

283+
DEFINE_CLASS(prepare_creds,
284+
struct cred *,
285+
if (_T) put_cred(_T),
286+
prepare_creds(), void)
287+
283288
DEFINE_FREE(put_cred, struct cred *, if (!IS_ERR_OR_NULL(_T)) put_cred(_T))
284289

285290
/**

include/linux/sched/coredump.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#define SUID_DUMP_USER 1 /* Dump as user of process */
99
#define SUID_DUMP_ROOT 2 /* Dump as root */
1010

11-
static inline unsigned long __mm_flags_get_dumpable(struct mm_struct *mm)
11+
static inline unsigned long __mm_flags_get_dumpable(const struct mm_struct *mm)
1212
{
1313
/*
1414
* By convention, dumpable bits are contained in first 32 bits of the

kernel/trace/trace_events_user.c

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,12 +1449,7 @@ static struct trace_event_functions user_event_funcs = {
14491449

14501450
static int user_event_set_call_visible(struct user_event *user, bool visible)
14511451
{
1452-
int ret;
1453-
const struct cred *old_cred;
1454-
struct cred *cred;
1455-
1456-
cred = prepare_creds();
1457-
1452+
CLASS(prepare_creds, cred)();
14581453
if (!cred)
14591454
return -ENOMEM;
14601455

@@ -1469,17 +1464,12 @@ static int user_event_set_call_visible(struct user_event *user, bool visible)
14691464
*/
14701465
cred->fsuid = GLOBAL_ROOT_UID;
14711466

1472-
old_cred = override_creds(cred);
1473-
1474-
if (visible)
1475-
ret = trace_add_event_call(&user->call);
1476-
else
1477-
ret = trace_remove_event_call(&user->call);
1478-
1479-
revert_creds(old_cred);
1480-
put_cred(cred);
1467+
scoped_with_creds(cred) {
1468+
if (visible)
1469+
return trace_add_event_call(&user->call);
14811470

1482-
return ret;
1471+
return trace_remove_event_call(&user->call);
1472+
}
14831473
}
14841474

14851475
static int destroy_user_event(struct user_event *user)

0 commit comments

Comments
 (0)