aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c76
1 files changed, 48 insertions, 28 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 02bfd980a40c..49a1c61433b7 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1275,6 +1275,53 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
1275 spin_unlock(&p->fs->lock); 1275 spin_unlock(&p->fs->lock);
1276} 1276}
1277 1277
1278static void bprm_fill_uid(struct linux_binprm *bprm)
1279{
1280 struct inode *inode;
1281 unsigned int mode;
1282 kuid_t uid;
1283 kgid_t gid;
1284
1285 /* clear any previous set[ug]id data from a previous binary */
1286 bprm->cred->euid = current_euid();
1287 bprm->cred->egid = current_egid();
1288
1289 if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
1290 return;
1291
1292 if (task_no_new_privs(current))
1293 return;
1294
1295 inode = file_inode(bprm->file);
1296 mode = READ_ONCE(inode->i_mode);
1297 if (!(mode & (S_ISUID|S_ISGID)))
1298 return;
1299
1300 /* Be careful if suid/sgid is set */
1301 mutex_lock(&inode->i_mutex);
1302
1303 /* reload atomically mode/uid/gid now that lock held */
1304 mode = inode->i_mode;
1305 uid = inode->i_uid;
1306 gid = inode->i_gid;
1307 mutex_unlock(&inode->i_mutex);
1308
1309 /* We ignore suid/sgid if there are no mappings for them in the ns */
1310 if (!kuid_has_mapping(bprm->cred->user_ns, uid) ||
1311 !kgid_has_mapping(bprm->cred->user_ns, gid))
1312 return;
1313
1314 if (mode & S_ISUID) {
1315 bprm->per_clear |= PER_CLEAR_ON_SETID;
1316 bprm->cred->euid = uid;
1317 }
1318
1319 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
1320 bprm->per_clear |= PER_CLEAR_ON_SETID;
1321 bprm->cred->egid = gid;
1322 }
1323}
1324
1278/* 1325/*
1279 * Fill the binprm structure from the inode. 1326 * Fill the binprm structure from the inode.
1280 * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes 1327 * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
@@ -1283,36 +1330,9 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
1283 */ 1330 */
1284int prepare_binprm(struct linux_binprm *bprm) 1331int prepare_binprm(struct linux_binprm *bprm)
1285{ 1332{
1286 struct inode *inode = file_inode(bprm->file);
1287 umode_t mode = inode->i_mode;
1288 int retval; 1333 int retval;
1289 1334
1290 1335 bprm_fill_uid(bprm);
1291 /* clear any previous set[ug]id data from a previous binary */
1292 bprm->cred->euid = current_euid();
1293 bprm->cred->egid = current_egid();
1294
1295 if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) &&
1296 !task_no_new_privs(current) &&
1297 kuid_has_mapping(bprm->cred->user_ns, inode->i_uid) &&
1298 kgid_has_mapping(bprm->cred->user_ns, inode->i_gid)) {
1299 /* Set-uid? */
1300 if (mode & S_ISUID) {
1301 bprm->per_clear |= PER_CLEAR_ON_SETID;
1302 bprm->cred->euid = inode->i_uid;
1303 }
1304
1305 /* Set-gid? */
1306 /*
1307 * If setgid is set but no group execute bit then this
1308 * is a candidate for mandatory locking, not a setgid
1309 * executable.
1310 */
1311 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
1312 bprm->per_clear |= PER_CLEAR_ON_SETID;
1313 bprm->cred->egid = inode->i_gid;
1314 }
1315 }
1316 1336
1317 /* fill in binprm security blob */ 1337 /* fill in binprm security blob */
1318 retval = security_bprm_set_creds(bprm); 1338 retval = security_bprm_set_creds(bprm);