#define CAP_SETFCAP         31
 
 #ifdef __KERNEL__
-/*
- * Bounding set
- */
-extern kernel_cap_t cap_bset;
 
 /*
  * Internal kernel functions only
 
 #include <linux/xfrm.h>
 #include <net/flow.h>
 
+/*
+ * Bounding set
+ */
+extern kernel_cap_t cap_bset;
+
+extern unsigned securebits;
+
 struct ctl_table;
 
 /*
 
  *
  * Copyright (C) 1997  Andrew Main <zefram@fysh.org>
  *
- * Integrated into 2.1.97+,  Andrew G. Morgan <morgan@transmeta.com>
+ * Integrated into 2.1.97+,  Andrew G. Morgan <morgan@kernel.org>
  * 30 May 2002:        Cleanup, Robert M. Love <rml@tech9.net>
  */ 
 
 #include <linux/syscalls.h>
 #include <asm/uaccess.h>
 
-unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
-kernel_cap_t cap_bset = CAP_INIT_EFF_SET;
-
 /*
  * This lock protects task->cap_* for all tasks including current.
  * Locking rule: acquire this prior to tasklist_lock.
 
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
-#include <linux/capability.h>
+#include <linux/security.h>
 #include <linux/ctype.h>
 #include <linux/utsname.h>
 #include <linux/smp_lock.h>
                .proc_handler   = &proc_dointvec_taint,
        },
 #endif
+#ifdef CONFIG_SECURITY_CAPABILITIES
        {
                .procname       = "cap-bound",
                .data           = &cap_bset,
                .mode           = 0600,
                .proc_handler   = &proc_dointvec_bset,
        },
+#endif /* def CONFIG_SECURITY_CAPABILITIES */
 #ifdef CONFIG_BLK_DEV_INITRD
        {
                .ctl_name       = KERN_REALROOTDEV,
        return 0;
 }
 
+#ifdef CONFIG_SECURITY_CAPABILITIES
 /*
  *     init may raise the set.
  */
- 
+
 int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp,
                        void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
                                do_proc_dointvec_bset_conv,&op);
 }
+#endif /* def CONFIG_SECURITY_CAPABILITIES */
 
 /*
  *     Taint values can only be increased
 
        { KERN_NODENAME,                "hostname" },
        { KERN_DOMAINNAME,              "domainname" },
 
+#ifdef CONFIG_SECURITY_CAPABILITIES
        { KERN_CAP_BSET,                "cap-bound" },
+#endif /* def CONFIG_SECURITY_CAPABILITIES */
+
        { KERN_PANIC,                   "panic" },
        { KERN_REALROOTDEV,             "real-root-dev" },
 
                            (table->strategy == sysctl_ms_jiffies) ||
                            (table->proc_handler == proc_dostring) ||
                            (table->proc_handler == proc_dointvec) ||
+#ifdef CONFIG_SECURITY_CAPABILITIES
                            (table->proc_handler == proc_dointvec_bset) ||
+#endif /* def CONFIG_SECURITY_CAPABILITIES */
                            (table->proc_handler == proc_dointvec_minmax) ||
                            (table->proc_handler == proc_dointvec_jiffies) ||
                            (table->proc_handler == proc_dointvec_userhz_jiffies) ||
 
 #include <linux/hugetlb.h>
 #include <linux/mount.h>
 
+#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
+/*
+ * Because of the reduced scope of CAP_SETPCAP when filesystem
+ * capabilities are in effect, it is safe to allow this capability to
+ * be available in the default configuration.
+ */
+# define CAP_INIT_BSET  CAP_FULL_SET
+#else /* ie. ndef CONFIG_SECURITY_FILE_CAPABILITIES */
+# define CAP_INIT_BSET  CAP_INIT_EFF_SET
+#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
+
+kernel_cap_t cap_bset = CAP_INIT_BSET;    /* systemwide capability bound */
+EXPORT_SYMBOL(cap_bset);
+
+/* Global security state */
+
+unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
+EXPORT_SYMBOL(securebits);
+
 int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
 {
        NETLINK_CB(skb).eff_cap = current->cap_effective;
        return 0;
 }
 
+#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
+
+static inline int cap_block_setpcap(struct task_struct *target)
+{
+       /*
+        * No support for remote process capability manipulation with
+        * filesystem capability support.
+        */
+       return (target != current);
+}
+
+static inline int cap_inh_is_capped(void)
+{
+       /*
+        * return 1 if changes to the inheritable set are limited
+        * to the old permitted set.
+        */
+       return !cap_capable(current, CAP_SETPCAP);
+}
+
+#else /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */
+
+static inline int cap_block_setpcap(struct task_struct *t) { return 0; }
+static inline int cap_inh_is_capped(void) { return 1; }
+
+#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
+
 int cap_capset_check (struct task_struct *target, kernel_cap_t *effective,
                      kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
-       /* Derived from kernel/capability.c:sys_capset. */
-       /* verify restrictions on target's new Inheritable set */
-       if (!cap_issubset (*inheritable,
-                          cap_combine (target->cap_inheritable,
-                                       current->cap_permitted))) {
+       if (cap_block_setpcap(target)) {
+               return -EPERM;
+       }
+       if (cap_inh_is_capped()
+           && !cap_issubset(*inheritable,
+                            cap_combine(target->cap_inheritable,
+                                        current->cap_permitted))) {
+               /* incapable of using this inheritable set */
                return -EPERM;
        }
 
 
                         kernel_cap_t * inheritable, kernel_cap_t * permitted)
 {
        *effective = *inheritable = *permitted = 0;
-       if (!issecure(SECURE_NOROOT)) {
-               if (target->euid == 0) {
-                       *permitted |= (~0 & ~CAP_FS_MASK);
-                       *effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK);
-               }
-               if (target->fsuid == 0) {
-                       *permitted |= CAP_FS_MASK;
-                       *effective |= CAP_FS_MASK;
-               }
+       if (target->euid == 0) {
+               *permitted |= (~0 & ~CAP_FS_MASK);
+               *effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK);
+       }
+       if (target->fsuid == 0) {
+               *permitted |= CAP_FS_MASK;
+               *effective |= CAP_FS_MASK;
        }
        return 0;
 }