aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/exec.c19
-rw-r--r--include/linux/capability.h1
-rw-r--r--kernel/capability.c16
3 files changed, 32 insertions, 4 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 3cf2cfced97a..fdf53f0c421b 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1275,8 +1275,22 @@ EXPORT_SYMBOL(flush_old_exec);
1275 1275
1276void would_dump(struct linux_binprm *bprm, struct file *file) 1276void would_dump(struct linux_binprm *bprm, struct file *file)
1277{ 1277{
1278 if (inode_permission(file_inode(file), MAY_READ) < 0) 1278 struct inode *inode = file_inode(file);
1279 if (inode_permission(inode, MAY_READ) < 0) {
1280 struct user_namespace *old, *user_ns;
1279 bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; 1281 bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
1282
1283 /* Ensure mm->user_ns contains the executable */
1284 user_ns = old = bprm->mm->user_ns;
1285 while ((user_ns != &init_user_ns) &&
1286 !privileged_wrt_inode_uidgid(user_ns, inode))
1287 user_ns = user_ns->parent;
1288
1289 if (old != user_ns) {
1290 bprm->mm->user_ns = get_user_ns(user_ns);
1291 put_user_ns(old);
1292 }
1293 }
1280} 1294}
1281EXPORT_SYMBOL(would_dump); 1295EXPORT_SYMBOL(would_dump);
1282 1296
@@ -1306,7 +1320,6 @@ void setup_new_exec(struct linux_binprm * bprm)
1306 !gid_eq(bprm->cred->gid, current_egid())) { 1320 !gid_eq(bprm->cred->gid, current_egid())) {
1307 current->pdeath_signal = 0; 1321 current->pdeath_signal = 0;
1308 } else { 1322 } else {
1309 would_dump(bprm, bprm->file);
1310 if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) 1323 if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)
1311 set_dumpable(current->mm, suid_dumpable); 1324 set_dumpable(current->mm, suid_dumpable);
1312 } 1325 }
@@ -1741,6 +1754,8 @@ static int do_execveat_common(int fd, struct filename *filename,
1741 if (retval < 0) 1754 if (retval < 0)
1742 goto out; 1755 goto out;
1743 1756
1757 would_dump(bprm, bprm->file);
1758
1744 retval = exec_binprm(bprm); 1759 retval = exec_binprm(bprm);
1745 if (retval < 0) 1760 if (retval < 0)
1746 goto out; 1761 goto out;
diff --git a/include/linux/capability.h b/include/linux/capability.h
index d6088e2a7668..6ffb67e10c06 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -240,6 +240,7 @@ static inline bool ns_capable_noaudit(struct user_namespace *ns, int cap)
240 return true; 240 return true;
241} 241}
242#endif /* CONFIG_MULTIUSER */ 242#endif /* CONFIG_MULTIUSER */
243extern bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct inode *inode);
243extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap); 244extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
244extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap); 245extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
245extern bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns); 246extern bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns);
diff --git a/kernel/capability.c b/kernel/capability.c
index dfa0e4528b0b..4984e1f552eb 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -457,6 +457,19 @@ bool file_ns_capable(const struct file *file, struct user_namespace *ns,
457EXPORT_SYMBOL(file_ns_capable); 457EXPORT_SYMBOL(file_ns_capable);
458 458
459/** 459/**
460 * privileged_wrt_inode_uidgid - Do capabilities in the namespace work over the inode?
461 * @ns: The user namespace in question
462 * @inode: The inode in question
463 *
464 * Return true if the inode uid and gid are within the namespace.
465 */
466bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct inode *inode)
467{
468 return kuid_has_mapping(ns, inode->i_uid) &&
469 kgid_has_mapping(ns, inode->i_gid);
470}
471
472/**
460 * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped 473 * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped
461 * @inode: The inode in question 474 * @inode: The inode in question
462 * @cap: The capability in question 475 * @cap: The capability in question
@@ -469,8 +482,7 @@ bool capable_wrt_inode_uidgid(const struct inode *inode, int cap)
469{ 482{
470 struct user_namespace *ns = current_user_ns(); 483 struct user_namespace *ns = current_user_ns();
471 484
472 return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid) && 485 return ns_capable(ns, cap) && privileged_wrt_inode_uidgid(ns, inode);
473 kgid_has_mapping(ns, inode->i_gid);
474} 486}
475EXPORT_SYMBOL(capable_wrt_inode_uidgid); 487EXPORT_SYMBOL(capable_wrt_inode_uidgid);
476 488