]> git.ipfire.org Git - people/ms/linux.git/blobdiff - kernel/capability.c
Importing "grsecurity-3.1-3.19.2-201503201903.patch"
[people/ms/linux.git] / kernel / capability.c
index 989f5bfc57dcfde3046b2756ddd2aac59da1ec73..d317ca0a87daaaacf0cb2ed394eccffe7bc1c1e8 100644 (file)
@@ -192,6 +192,9 @@ SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr)
                 * before modification is attempted and the application
                 * fails.
                 */
+               if (tocopy > ARRAY_SIZE(kdata))
+                       return -EFAULT;
+
                if (copy_to_user(dataptr, kdata, tocopy
                                 * sizeof(struct __user_cap_data_struct))) {
                        return -EFAULT;
@@ -297,10 +300,11 @@ bool has_ns_capability(struct task_struct *t,
        int ret;
 
        rcu_read_lock();
-       ret = security_capable(__task_cred(t), ns, cap);
+       ret = security_capable(__task_cred(t), ns, cap) == 0 &&
+               gr_task_is_capable(t, __task_cred(t), cap);
        rcu_read_unlock();
 
-       return (ret == 0);
+       return ret;
 }
 
 /**
@@ -337,10 +341,10 @@ bool has_ns_capability_noaudit(struct task_struct *t,
        int ret;
 
        rcu_read_lock();
-       ret = security_capable_noaudit(__task_cred(t), ns, cap);
+       ret = security_capable_noaudit(__task_cred(t), ns, cap) == 0 && gr_task_is_capable_nolog(t, cap);
        rcu_read_unlock();
 
-       return (ret == 0);
+       return ret;
 }
 
 /**
@@ -378,7 +382,7 @@ bool ns_capable(struct user_namespace *ns, int cap)
                BUG();
        }
 
-       if (security_capable(current_cred(), ns, cap) == 0) {
+       if (security_capable(current_cred(), ns, cap) == 0 && gr_is_capable(cap)) {
                current->flags |= PF_SUPERPRIV;
                return true;
        }
@@ -386,6 +390,21 @@ bool ns_capable(struct user_namespace *ns, int cap)
 }
 EXPORT_SYMBOL(ns_capable);
 
+bool ns_capable_nolog(struct user_namespace *ns, int cap)
+{
+       if (unlikely(!cap_valid(cap))) {
+               printk(KERN_CRIT "capable_nolog() called with invalid cap=%u\n", cap);
+               BUG();
+       }
+
+       if (security_capable_noaudit(current_cred(), ns, cap) == 0 && gr_is_capable_nolog(cap)) {
+               current->flags |= PF_SUPERPRIV;
+               return true;
+       }
+       return false;
+}
+EXPORT_SYMBOL(ns_capable_nolog);
+
 /**
  * file_ns_capable - Determine if the file's opener had a capability in effect
  * @file:  The file we want to check
@@ -427,6 +446,12 @@ bool capable(int cap)
 }
 EXPORT_SYMBOL(capable);
 
+bool capable_nolog(int cap)
+{
+       return ns_capable_nolog(&init_user_ns, cap);
+}
+EXPORT_SYMBOL(capable_nolog);
+
 /**
  * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped
  * @inode: The inode in question
@@ -444,3 +469,12 @@ bool capable_wrt_inode_uidgid(const struct inode *inode, int cap)
                kgid_has_mapping(ns, inode->i_gid);
 }
 EXPORT_SYMBOL(capable_wrt_inode_uidgid);
+
+bool capable_wrt_inode_uidgid_nolog(const struct inode *inode, int cap)
+{
+       struct user_namespace *ns = current_user_ns();
+
+       return ns_capable_nolog(ns, cap) && kuid_has_mapping(ns, inode->i_uid) &&
+               kgid_has_mapping(ns, inode->i_gid);
+}
+EXPORT_SYMBOL(capable_wrt_inode_uidgid_nolog);