mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Serge E. Hallyn" <serge@hallyn.com>
To: Nicholas Miell <nmiell@comcast.net>
Cc: "Serge E. Hallyn" <serge@hallyn.com>,
	"Eric W. Biederman" <ebiederm@xmission.com>,
	"Serge E. Hallyn" <serue@us.ibm.com>,
	lkml <linux-kernel@vger.kernel.org>,
	linux-security-module@vger.kernel.org, chrisw@sous-sol.org
Subject: Re: [RFC] [PATCH] file posix capabilities
Date: Tue, 15 Aug 2006 14:41:51 -0500	[thread overview]
Message-ID: <20060815194151.GA8596@vino.hallyn.com> (raw)
In-Reply-To: <1155670262.2432.4.camel@entropy>

Quoting Nicholas Miell (nmiell@comcast.net):
> On Tue, 2006-08-15 at 07:20 -0500, Serge E. Hallyn wrote:
> > Quoting Serge E. Hallyn (serge@hallyn.com):
> > > > Make it an arbitrary length bitfield with a defined byte order (little
> > > > endian, probably). Bits at offsets greater than the length of the
> > > > bitfield are defined to be zero. If the kernel encounters a set bit that
> > > > it doesn't recognizes, fail with EPERM. If userspace attempts to set a
> > > > bit that the kernel doesn't recognize, fail with EINVAL.
> > > > 
> > > > It's extensible (as new capability bits are added, the length of the
> > > > bitfield grows), backward compatible (as long as there are no unknown
> > > > bits set, it'll still work) and secure (if an unknown bit is set, the
> > > > kernel fails immediately, so there's no chance of a "secure" app running
> > > > with less privileges than it expects and opening up a security hole).
> > > 
> > > Sounds good.
> > > 
> > > The version number will imply the bitfield length, or do we feel warm
> > > fuzzies if the length is redundantly encoded in the structure?
> > 
> > nm, 'encoded in the structure' clearly is silly.
> > 
> 
> There isn't really a version number, just recognized and unrecognized

Well, there is, defined in include/linux/capability.h, but it has never
changed thus far, and tying it to the bitfield length could get ugly as
things change.

In the below patch, the length is simply defined in
include/linux/capability.h, nothing fancy.  If anything beyond the known
capability bits is set to 1, we refuse exec permission.

> capability bits. If you wanted, you could use a single byte to give a
> binary CAP_DAC_OVERRIDE, with capability bits 8-30 being "stored" in
> not-present bytes and therefore assumed to be zero.

From: Serge E. Hallyn <serue@us.ibm.com>
Subject: [PATCH 1/1] security: introduce fs caps

Implement filesystem posix capabilities.  This allows programs to
be given a subset of root's powers regardless of who runs them,
without having to use setuid and giving the binary all of root's
powers.

This version works with Kaigai Kohei's userspace tools, found at
http://www.kaigai.gr.jp/pub/fscaps-1.0-kg.src.rpm under
http://www.kaigai.gr.jp/index.php?FrontPage#b556e50d.

Changelog:
	Aug 15:
	Handle endianness of xattrs.
	Enforce capability version match between kernel and disk.
	Enforce that no bits beyond the known max capability are
	set, else return -EPERM.
	With this extra processing, it may be worth reconsidering
	doing all the work at bprm_set_security rather than
	d_instantiate.

	Aug 10:
	Always call getxattr at bprm_set_security, rather than
	caching it at d_instantiate.

Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>
---
 include/linux/capability.h |    2 +
 security/Kconfig           |   10 +++++
 security/commoncap.c       |   85 +++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 96 insertions(+), 1 deletions(-)

diff --git a/include/linux/capability.h b/include/linux/capability.h
index 6548b35..8b1932c 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -288,6 +288,8 @@ #define CAP_AUDIT_WRITE      29
 
 #define CAP_AUDIT_CONTROL    30
 
+#define CAP_NUMCAPS	     30
+
 #ifdef __KERNEL__
 /* 
  * Bounding set
diff --git a/security/Kconfig b/security/Kconfig
index 67785df..ce2bac7 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -80,6 +80,16 @@ config SECURITY_CAPABILITIES
 	  This enables the "default" Linux capabilities functionality.
 	  If you are unsure how to answer this question, answer Y.
 
+config SECURITY_FS_CAPABILITIES
+	bool "Filesystem Capabilities"
+	depends on SECURITY_CAPABILITIES
+	default n
+	help
+	  This enables filesystem capabilities, allowing you to give
+	  binaries a subset of root's powers without using setuid 0.
+
+	  If in doubt, answer N.
+
 config SECURITY_ROOTPLUG
 	tristate "Root Plug Support"
 	depends on USB && SECURITY
diff --git a/security/commoncap.c b/security/commoncap.c
index f50fc29..6bf030d 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -109,11 +109,55 @@ void cap_capset_set (struct task_struct 
 	target->cap_permitted = *permitted;
 }
 
+#define XATTR_CAPS_SUFFIX "capability"
+#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
+struct vfs_cap_data_struct {
+	__u32 version;
+	__u32 effective;
+	__u32 permitted;
+	__u32 inheritable;
+};
+
+static inline void convert_to_le(struct vfs_cap_data_struct *cap)
+{
+	cap->version = le32_to_cpu(cap->version);
+	cap->effective = le32_to_cpu(cap->effective);
+	cap->permitted = le32_to_cpu(cap->permitted);
+	cap->inheritable = le32_to_cpu(cap->inheritable);
+}
+
+static int check_cap_sanity(struct vfs_cap_data_struct *cap)
+{
+	int i;
+
+	if (cap->version != _LINUX_CAPABILITY_VERSION)
+		return -EPERM;
+
+	for (i=CAP_NUMCAPS; i<sizeof(cap->effective); i++) {
+		if (cap->effective & CAP_TO_MASK(i))
+			return -EPERM;
+	}
+	for (i=CAP_NUMCAPS; i<sizeof(cap->permitted); i++) {
+		if (cap->permitted & CAP_TO_MASK(i))
+			return -EPERM;
+	}
+	for (i=CAP_NUMCAPS; i<sizeof(cap->inheritable); i++) {
+		if (cap->inheritable & CAP_TO_MASK(i))
+			return -EPERM;
+	}
+
+	return 0;
+}
+
 int cap_bprm_set_security (struct linux_binprm *bprm)
 {
+	struct dentry *dentry;
+	ssize_t rc;
+	struct vfs_cap_data_struct cap_struct;
+	struct inode *inode;
+
 	/* Copied from fs/exec.c:prepare_binprm. */
 
-	/* We don't have VFS support for capabilities yet */
 	cap_clear (bprm->cap_inheritable);
 	cap_clear (bprm->cap_permitted);
 	cap_clear (bprm->cap_effective);
@@ -134,6 +178,45 @@ int cap_bprm_set_security (struct linux_
 		if (bprm->e_uid == 0)
 			cap_set_full (bprm->cap_effective);
 	}
+
+#ifdef CONFIG_SECURITY_FS_CAPABILITIES
+	/* Locate any VFS capabilities: */
+
+	dentry = dget(bprm->file->f_dentry);
+	inode = dentry->d_inode;
+	if (!inode->i_op || !inode->i_op->getxattr) {
+		dput(dentry);
+		return 0;
+	}
+
+	rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &cap_struct,
+						sizeof(cap_struct));
+	dput(dentry);
+
+	if (rc == -ENODATA)
+		return 0;
+
+	if (rc < 0) {
+		printk(KERN_NOTICE "%s: Error (%d) getting xattr\n",
+				__FUNCTION__, rc);
+		return rc;
+	}
+
+	if (rc != sizeof(cap_struct)) {
+		printk(KERN_NOTICE "%s: got wrong size for getxattr (%d)\n",
+					__FUNCTION__, rc);
+		return -EPERM;
+	}
+	
+	convert_to_le(&cap_struct);
+	if (check_cap_sanity(&cap_struct))
+		return -EPERM;
+
+	bprm->cap_effective = cap_struct.effective;
+	bprm->cap_permitted = cap_struct.permitted;
+	bprm->cap_inheritable = cap_struct.inheritable;
+
+#endif
 	return 0;
 }
 
-- 
1.4.2


  reply	other threads:[~2006-08-15 19:41 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-07-30  1:13 Serge E. Hallyn
2006-08-14 22:06 ` Serge E. Hallyn
2006-08-15  0:20   ` Eric W. Biederman
2006-08-15  2:06     ` Serge E. Hallyn
2006-08-15  3:29       ` Eric W. Biederman
2006-08-15  4:22         ` Nicholas Miell
2006-08-15 11:49           ` Serge E. Hallyn
2006-08-15 12:20             ` Serge E. Hallyn
2006-08-15 19:31               ` Nicholas Miell
2006-08-15 19:41                 ` Serge E. Hallyn [this message]
2006-08-15 16:18             ` Stephen Smalley
2006-08-15 16:36               ` Casey Schaufler
2006-08-16  2:42               ` Serge E. Hallyn
2006-08-16 13:20                 ` Stephen Smalley
2006-08-17 12:00                   ` Joshua Brindle
2006-08-17 12:28                     ` Stephen Smalley
2006-08-21 20:36                       ` Serge E. Hallyn
2006-08-28 21:39                         ` Serge E. Hallyn
2006-08-29 18:37                           ` Seth Arnold
2006-08-29 19:58                             ` Serge E. Hallyn
2006-08-19  2:02                   ` Crispin Cowan
2006-08-19 17:08                     ` Casey Schaufler
2006-08-22  2:50                     ` Serge E. Hallyn
2006-08-22  3:19                       ` Seth Arnold
2006-08-19  2:02           ` Crispin Cowan
     [not found]   ` <44E1153D.9000102@ak.jp.nec.com>
     [not found]     ` <20060815021612.GC16220@sergelap.austin.ibm.com>
2006-08-15  3:48       ` KaiGai Kohei
2006-08-15 12:04         ` Serge E. Hallyn
2006-08-15 16:02   ` Casey Schaufler
2006-08-16  2:25     ` Serge E. Hallyn
2006-08-16  2:43 Albert Cahalan
2006-08-16  3:23 ` Serge E. Hallyn
2006-08-16  3:44 ` Casey Schaufler

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060815194151.GA8596@vino.hallyn.com \
    --to=serge@hallyn.com \
    --cc=chrisw@sous-sol.org \
    --cc=ebiederm@xmission.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=nmiell@comcast.net \
    --cc=serue@us.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome