diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 76 |
1 files changed, 48 insertions, 28 deletions
@@ -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 | ||
1278 | static 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 | */ |
1284 | int prepare_binprm(struct linux_binprm *bprm) | 1331 | int 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); |