All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] selinux: new permission for chmod on suid or sgid files
@ 2008-10-17 15:40 Eric Paris
  2008-10-17 16:52 ` Stephen Smalley
  0 siblings, 1 reply; 23+ messages in thread
From: Eric Paris @ 2008-10-17 15:40 UTC (permalink / raw)
  To: selinux; +Cc: sds, jmorris, dwalsh, sgrubb

This patch adds a new permission, setsuid, to the file class.  This
permission is checked any time a file has its attributes modified
(setattr) and the setuid or setgid bits are involved.  The purpose for
this change is to further allow selinux to confine administrative
duties.  The example explains when the permission is needed and when it
is not:

Start with a file with chmod 0644.
chmod u+s  (0644 -> 4644) { setattr setsuid }
chmod u-r  (4644 -> 4244) { setattr setsuid }
chmod u-s  (4244 -> 0244) { setattr setsuid }
chmod u+r  (0244 -> 0644) { setattr }

If either the starting or the final attributes will have the setuid or
setgid bits set you need this permission.

Signed-off-by: Eric Paris <eparis@redhat.com>

---

 security/selinux/hooks.c                     |   22 ++++++++++++++++++++--
 security/selinux/include/av_perm_to_string.h |    1 +
 security/selinux/include/av_permissions.h    |    1 +
 security/selinux/include/class_to_string.h   |    4 ++++
 security/selinux/include/security.h          |    2 ++
 security/selinux/selinuxfs.c                 |    3 ++-
 security/selinux/ss/services.c               |    3 +++
 7 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 576e511..58af86a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2659,6 +2659,8 @@ static int selinux_inode_permission(struct inode *inode, int mask)
 static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 {
 	int rc;
+	unsigned int mode = dentry->d_inode->i_mode;
+	u32 av = 0;
 
 	rc = secondary_ops->inode_setattr(dentry, iattr);
 	if (rc)
@@ -2667,11 +2669,27 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 	if (iattr->ia_valid & ATTR_FORCE)
 		return 0;
 
+	/*
+	 * are we changing mode?
+	 * does policy support seperate suid/sgid checks?
+	 * is this a regular file?
+	 * do either the old inode->i_mode or the new iattr->i_mode have the
+	 * suid/sgid bits set?
+	 */
+	if ((iattr->ia_valid & ATTR_MODE) &&
+	    selinux_policycap_setsuidperm &&
+	    (S_ISREG(mode)) &&
+	    ((iattr->ia_mode & (S_ISUID | S_ISGID)) ||
+	     (mode & (S_ISUID | S_ISGID))))
+			av |= FILE__SETSUID;
+
 	if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
 			       ATTR_ATIME_SET | ATTR_MTIME_SET))
-		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
+		av |= FILE__SETATTR;
+	else
+		av = FILE__WRITE;
 
-	return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
+	return dentry_has_perm(current, NULL, dentry, av);
 }
 
 static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index 1223b4f..c6c5c0e 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -19,6 +19,7 @@
    S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
    S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
    S_(SECCLASS_FILE, FILE__OPEN, "open")
+   S_(SECCLASS_FILE, FILE__SETSUID, "setsuid")
    S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
    S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
    S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index c4c5116..cd6d566 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -101,6 +101,7 @@
 #define FILE__ENTRYPOINT                          0x00040000UL
 #define FILE__EXECMOD                             0x00080000UL
 #define FILE__OPEN                                0x00100000UL
+#define FILE__SETSUID                             0x00200000UL
 #define LNK_FILE__IOCTL                           0x00000001UL
 #define LNK_FILE__READ                            0x00000002UL
 #define LNK_FILE__WRITE                           0x00000004UL
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
index bd813c3..0d11270 100644
--- a/security/selinux/include/class_to_string.h
+++ b/security/selinux/include/class_to_string.h
@@ -72,3 +72,7 @@
     S_(NULL)
     S_("peer")
     S_("capability2")
+    S_(NULL)
+    S_(NULL)
+    S_(NULL)
+    S_(NULL)
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 7244737..a604f05 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -56,12 +56,14 @@ extern int selinux_mls_enabled;
 enum {
 	POLICYDB_CAPABILITY_NETPEER,
 	POLICYDB_CAPABILITY_OPENPERM,
+	POLICYDB_CAPABILITY_SETSUIDPERM,
 	__POLICYDB_CAPABILITY_MAX
 };
 #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
 
 extern int selinux_policycap_netpeer;
 extern int selinux_policycap_openperm;
+extern int selinux_policycap_setsuidperm;
 
 /*
  * type_datum properties
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 69c9dcc..26ef62f 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -42,7 +42,8 @@
 /* Policy capability filenames */
 static char *policycap_names[] = {
 	"network_peer_controls",
-	"open_perms"
+	"open_perms",
+	"setsuid_perms",
 };
 
 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 343c8ab..9ecd8e7 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -64,6 +64,7 @@ unsigned int policydb_loaded_version;
 
 int selinux_policycap_netpeer;
 int selinux_policycap_openperm;
+int selinux_policycap_setsuidperm;
 
 /*
  * This is declared in avc.c
@@ -1615,6 +1616,8 @@ static void security_load_policycaps(void)
 						  POLICYDB_CAPABILITY_NETPEER);
 	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
 						  POLICYDB_CAPABILITY_OPENPERM);
+	selinux_policycap_setsuidperm = ebitmap_get_bit(&policydb.policycaps,
+						  POLICYDB_CAPABILITY_SETSUIDPERM);
 }
 
 extern void selinux_complete_init(void);



--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 15:40 [PATCH] selinux: new permission for chmod on suid or sgid files Eric Paris
@ 2008-10-17 16:52 ` Stephen Smalley
  2008-10-17 17:24   ` Stephen Smalley
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2008-10-17 16:52 UTC (permalink / raw)
  To: Eric Paris; +Cc: selinux, jmorris, dwalsh, sgrubb

On Fri, 2008-10-17 at 11:40 -0400, Eric Paris wrote:
> This patch adds a new permission, setsuid, to the file class.  This
> permission is checked any time a file has its attributes modified
> (setattr) and the setuid or setgid bits are involved.  The purpose for
> this change is to further allow selinux to confine administrative
> duties.  The example explains when the permission is needed and when it
> is not:
> 
> Start with a file with chmod 0644.
> chmod u+s  (0644 -> 4644) { setattr setsuid }
> chmod u-r  (4644 -> 4244) { setattr setsuid }
> chmod u-s  (4244 -> 0244) { setattr setsuid }
> chmod u+r  (0244 -> 0644) { setattr }
> 
> If either the starting or the final attributes will have the setuid or
> setgid bits set you need this permission.

I'd like to understand better how this would be used.

Suppose that I want to control the ability to create/modify privileged
executables on the system.  Given that SELinux already controls
capability usage, I can already do that by labeling privileged
executable with an appropriate type and controlling the ability to
create/modify/relabelto that type, without being concerned about the
suid bit.  Why do I need this check?  And if I need this check, then
don't I need a similar check on setting/clearing file capabilities on a
given file?

Last concern I have is with this check not being adequately granular
since it is a single check for setting or clearing the suid or sgid bit
of a file owned by any user, whereas it seems more security-relevant to
be setting the suid bit on a root-owned executable than to be clearing
it or to be setting the suid bit on a sds-owned executable.  I'm not
sure how to write a useful policy that lets users do things that are
harmless or of no interest while still enforcing a useful goal.

> 
> Signed-off-by: Eric Paris <eparis@redhat.com>
> 
> ---
> 
>  security/selinux/hooks.c                     |   22 ++++++++++++++++++++--
>  security/selinux/include/av_perm_to_string.h |    1 +
>  security/selinux/include/av_permissions.h    |    1 +
>  security/selinux/include/class_to_string.h   |    4 ++++
>  security/selinux/include/security.h          |    2 ++
>  security/selinux/selinuxfs.c                 |    3 ++-
>  security/selinux/ss/services.c               |    3 +++
>  7 files changed, 33 insertions(+), 3 deletions(-)
> 
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 576e511..58af86a 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -2659,6 +2659,8 @@ static int selinux_inode_permission(struct inode *inode, int mask)
>  static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>  {
>  	int rc;
> +	unsigned int mode = dentry->d_inode->i_mode;
> +	u32 av = 0;
>  
>  	rc = secondary_ops->inode_setattr(dentry, iattr);
>  	if (rc)
> @@ -2667,11 +2669,27 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>  	if (iattr->ia_valid & ATTR_FORCE)
>  		return 0;
>  
> +	/*
> +	 * are we changing mode?
> +	 * does policy support seperate suid/sgid checks?
> +	 * is this a regular file?
> +	 * do either the old inode->i_mode or the new iattr->i_mode have the
> +	 * suid/sgid bits set?
> +	 */
> +	if ((iattr->ia_valid & ATTR_MODE) &&
> +	    selinux_policycap_setsuidperm &&
> +	    (S_ISREG(mode)) &&
> +	    ((iattr->ia_mode & (S_ISUID | S_ISGID)) ||
> +	     (mode & (S_ISUID | S_ISGID))))
> +			av |= FILE__SETSUID;
> +
>  	if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
>  			       ATTR_ATIME_SET | ATTR_MTIME_SET))
> -		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
> +		av |= FILE__SETATTR;
> +	else
> +		av = FILE__WRITE;
>  
> -	return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
> +	return dentry_has_perm(current, NULL, dentry, av);
>  }
>  
>  static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
> diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
> index 1223b4f..c6c5c0e 100644
> --- a/security/selinux/include/av_perm_to_string.h
> +++ b/security/selinux/include/av_perm_to_string.h
> @@ -19,6 +19,7 @@
>     S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
>     S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
>     S_(SECCLASS_FILE, FILE__OPEN, "open")
> +   S_(SECCLASS_FILE, FILE__SETSUID, "setsuid")
>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
>     S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
> diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
> index c4c5116..cd6d566 100644
> --- a/security/selinux/include/av_permissions.h
> +++ b/security/selinux/include/av_permissions.h
> @@ -101,6 +101,7 @@
>  #define FILE__ENTRYPOINT                          0x00040000UL
>  #define FILE__EXECMOD                             0x00080000UL
>  #define FILE__OPEN                                0x00100000UL
> +#define FILE__SETSUID                             0x00200000UL
>  #define LNK_FILE__IOCTL                           0x00000001UL
>  #define LNK_FILE__READ                            0x00000002UL
>  #define LNK_FILE__WRITE                           0x00000004UL
> diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
> index bd813c3..0d11270 100644
> --- a/security/selinux/include/class_to_string.h
> +++ b/security/selinux/include/class_to_string.h
> @@ -72,3 +72,7 @@
>      S_(NULL)
>      S_("peer")
>      S_("capability2")
> +    S_(NULL)
> +    S_(NULL)
> +    S_(NULL)
> +    S_(NULL)
> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
> index 7244737..a604f05 100644
> --- a/security/selinux/include/security.h
> +++ b/security/selinux/include/security.h
> @@ -56,12 +56,14 @@ extern int selinux_mls_enabled;
>  enum {
>  	POLICYDB_CAPABILITY_NETPEER,
>  	POLICYDB_CAPABILITY_OPENPERM,
> +	POLICYDB_CAPABILITY_SETSUIDPERM,
>  	__POLICYDB_CAPABILITY_MAX
>  };
>  #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
>  
>  extern int selinux_policycap_netpeer;
>  extern int selinux_policycap_openperm;
> +extern int selinux_policycap_setsuidperm;
>  
>  /*
>   * type_datum properties
> diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
> index 69c9dcc..26ef62f 100644
> --- a/security/selinux/selinuxfs.c
> +++ b/security/selinux/selinuxfs.c
> @@ -42,7 +42,8 @@
>  /* Policy capability filenames */
>  static char *policycap_names[] = {
>  	"network_peer_controls",
> -	"open_perms"
> +	"open_perms",
> +	"setsuid_perms",
>  };
>  
>  unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> index 343c8ab..9ecd8e7 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -64,6 +64,7 @@ unsigned int policydb_loaded_version;
>  
>  int selinux_policycap_netpeer;
>  int selinux_policycap_openperm;
> +int selinux_policycap_setsuidperm;
>  
>  /*
>   * This is declared in avc.c
> @@ -1615,6 +1616,8 @@ static void security_load_policycaps(void)
>  						  POLICYDB_CAPABILITY_NETPEER);
>  	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
>  						  POLICYDB_CAPABILITY_OPENPERM);
> +	selinux_policycap_setsuidperm = ebitmap_get_bit(&policydb.policycaps,
> +						  POLICYDB_CAPABILITY_SETSUIDPERM);
>  }
>  
>  extern void selinux_complete_init(void);
> 
-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 16:52 ` Stephen Smalley
@ 2008-10-17 17:24   ` Stephen Smalley
  2008-10-17 18:43     ` Daniel J Walsh
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2008-10-17 17:24 UTC (permalink / raw)
  To: Eric Paris; +Cc: selinux, jmorris, dwalsh, sgrubb

On Fri, 2008-10-17 at 12:52 -0400, Stephen Smalley wrote:
> On Fri, 2008-10-17 at 11:40 -0400, Eric Paris wrote:
> > This patch adds a new permission, setsuid, to the file class.  This
> > permission is checked any time a file has its attributes modified
> > (setattr) and the setuid or setgid bits are involved.  The purpose for
> > this change is to further allow selinux to confine administrative
> > duties.  The example explains when the permission is needed and when it
> > is not:
> > 
> > Start with a file with chmod 0644.
> > chmod u+s  (0644 -> 4644) { setattr setsuid }
> > chmod u-r  (4644 -> 4244) { setattr setsuid }
> > chmod u-s  (4244 -> 0244) { setattr setsuid }
> > chmod u+r  (0244 -> 0644) { setattr }
> > 
> > If either the starting or the final attributes will have the setuid or
> > setgid bits set you need this permission.
> 
> I'd like to understand better how this would be used.
> 
> Suppose that I want to control the ability to create/modify privileged
> executables on the system.  Given that SELinux already controls
> capability usage, I can already do that by labeling privileged
> executable with an appropriate type and controlling the ability to
> create/modify/relabelto that type, without being concerned about the
> suid bit.  Why do I need this check?  And if I need this check, then
> don't I need a similar check on setting/clearing file capabilities on a
> given file?

One other tidbit: I don't believe that this check will get applied in
the case where a suid/sgid binary is overwritten and the suid/sgid bits
are forcibly cleared (ATTR_FORCE), as the selinux_inode_setattr() hook
returns immediately in that case as it must not fail.

> Last concern I have is with this check not being adequately granular
> since it is a single check for setting or clearing the suid or sgid bit
> of a file owned by any user, whereas it seems more security-relevant to
> be setting the suid bit on a root-owned executable than to be clearing
> it or to be setting the suid bit on a sds-owned executable.  I'm not
> sure how to write a useful policy that lets users do things that are
> harmless or of no interest while still enforcing a useful goal.
> 
> > 
> > Signed-off-by: Eric Paris <eparis@redhat.com>
> > 
> > ---
> > 
> >  security/selinux/hooks.c                     |   22 ++++++++++++++++++++--
> >  security/selinux/include/av_perm_to_string.h |    1 +
> >  security/selinux/include/av_permissions.h    |    1 +
> >  security/selinux/include/class_to_string.h   |    4 ++++
> >  security/selinux/include/security.h          |    2 ++
> >  security/selinux/selinuxfs.c                 |    3 ++-
> >  security/selinux/ss/services.c               |    3 +++
> >  7 files changed, 33 insertions(+), 3 deletions(-)
> > 
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index 576e511..58af86a 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -2659,6 +2659,8 @@ static int selinux_inode_permission(struct inode *inode, int mask)
> >  static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
> >  {
> >  	int rc;
> > +	unsigned int mode = dentry->d_inode->i_mode;
> > +	u32 av = 0;
> >  
> >  	rc = secondary_ops->inode_setattr(dentry, iattr);
> >  	if (rc)
> > @@ -2667,11 +2669,27 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
> >  	if (iattr->ia_valid & ATTR_FORCE)
> >  		return 0;
> >  
> > +	/*
> > +	 * are we changing mode?
> > +	 * does policy support seperate suid/sgid checks?
> > +	 * is this a regular file?
> > +	 * do either the old inode->i_mode or the new iattr->i_mode have the
> > +	 * suid/sgid bits set?
> > +	 */
> > +	if ((iattr->ia_valid & ATTR_MODE) &&
> > +	    selinux_policycap_setsuidperm &&
> > +	    (S_ISREG(mode)) &&
> > +	    ((iattr->ia_mode & (S_ISUID | S_ISGID)) ||
> > +	     (mode & (S_ISUID | S_ISGID))))
> > +			av |= FILE__SETSUID;
> > +
> >  	if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
> >  			       ATTR_ATIME_SET | ATTR_MTIME_SET))
> > -		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
> > +		av |= FILE__SETATTR;
> > +	else
> > +		av = FILE__WRITE;
> >  
> > -	return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
> > +	return dentry_has_perm(current, NULL, dentry, av);
> >  }
> >  
> >  static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
> > diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
> > index 1223b4f..c6c5c0e 100644
> > --- a/security/selinux/include/av_perm_to_string.h
> > +++ b/security/selinux/include/av_perm_to_string.h
> > @@ -19,6 +19,7 @@
> >     S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
> >     S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
> >     S_(SECCLASS_FILE, FILE__OPEN, "open")
> > +   S_(SECCLASS_FILE, FILE__SETSUID, "setsuid")
> >     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
> >     S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
> >     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
> > diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
> > index c4c5116..cd6d566 100644
> > --- a/security/selinux/include/av_permissions.h
> > +++ b/security/selinux/include/av_permissions.h
> > @@ -101,6 +101,7 @@
> >  #define FILE__ENTRYPOINT                          0x00040000UL
> >  #define FILE__EXECMOD                             0x00080000UL
> >  #define FILE__OPEN                                0x00100000UL
> > +#define FILE__SETSUID                             0x00200000UL
> >  #define LNK_FILE__IOCTL                           0x00000001UL
> >  #define LNK_FILE__READ                            0x00000002UL
> >  #define LNK_FILE__WRITE                           0x00000004UL
> > diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
> > index bd813c3..0d11270 100644
> > --- a/security/selinux/include/class_to_string.h
> > +++ b/security/selinux/include/class_to_string.h
> > @@ -72,3 +72,7 @@
> >      S_(NULL)
> >      S_("peer")
> >      S_("capability2")
> > +    S_(NULL)
> > +    S_(NULL)
> > +    S_(NULL)
> > +    S_(NULL)
> > diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
> > index 7244737..a604f05 100644
> > --- a/security/selinux/include/security.h
> > +++ b/security/selinux/include/security.h
> > @@ -56,12 +56,14 @@ extern int selinux_mls_enabled;
> >  enum {
> >  	POLICYDB_CAPABILITY_NETPEER,
> >  	POLICYDB_CAPABILITY_OPENPERM,
> > +	POLICYDB_CAPABILITY_SETSUIDPERM,
> >  	__POLICYDB_CAPABILITY_MAX
> >  };
> >  #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
> >  
> >  extern int selinux_policycap_netpeer;
> >  extern int selinux_policycap_openperm;
> > +extern int selinux_policycap_setsuidperm;
> >  
> >  /*
> >   * type_datum properties
> > diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
> > index 69c9dcc..26ef62f 100644
> > --- a/security/selinux/selinuxfs.c
> > +++ b/security/selinux/selinuxfs.c
> > @@ -42,7 +42,8 @@
> >  /* Policy capability filenames */
> >  static char *policycap_names[] = {
> >  	"network_peer_controls",
> > -	"open_perms"
> > +	"open_perms",
> > +	"setsuid_perms",
> >  };
> >  
> >  unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
> > diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> > index 343c8ab..9ecd8e7 100644
> > --- a/security/selinux/ss/services.c
> > +++ b/security/selinux/ss/services.c
> > @@ -64,6 +64,7 @@ unsigned int policydb_loaded_version;
> >  
> >  int selinux_policycap_netpeer;
> >  int selinux_policycap_openperm;
> > +int selinux_policycap_setsuidperm;
> >  
> >  /*
> >   * This is declared in avc.c
> > @@ -1615,6 +1616,8 @@ static void security_load_policycaps(void)
> >  						  POLICYDB_CAPABILITY_NETPEER);
> >  	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
> >  						  POLICYDB_CAPABILITY_OPENPERM);
> > +	selinux_policycap_setsuidperm = ebitmap_get_bit(&policydb.policycaps,
> > +						  POLICYDB_CAPABILITY_SETSUIDPERM);
> >  }
> >  
> >  extern void selinux_complete_init(void);
> > 
-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 17:24   ` Stephen Smalley
@ 2008-10-17 18:43     ` Daniel J Walsh
  2008-10-17 18:53       ` Stephen Smalley
  0 siblings, 1 reply; 23+ messages in thread
From: Daniel J Walsh @ 2008-10-17 18:43 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Eric Paris, selinux, jmorris, sgrubb

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Stephen Smalley wrote:
> On Fri, 2008-10-17 at 12:52 -0400, Stephen Smalley wrote:
>> On Fri, 2008-10-17 at 11:40 -0400, Eric Paris wrote:
>>> This patch adds a new permission, setsuid, to the file class.  This
>>> permission is checked any time a file has its attributes modified
>>> (setattr) and the setuid or setgid bits are involved.  The purpose for
>>> this change is to further allow selinux to confine administrative
>>> duties.  The example explains when the permission is needed and when it
>>> is not:
>>>
>>> Start with a file with chmod 0644.
>>> chmod u+s  (0644 -> 4644) { setattr setsuid }
>>> chmod u-r  (4644 -> 4244) { setattr setsuid }
>>> chmod u-s  (4244 -> 0244) { setattr setsuid }
>>> chmod u+r  (0244 -> 0644) { setattr }
>>>
>>> If either the starting or the final attributes will have the setuid or
>>> setgid bits set you need this permission.
>> I'd like to understand better how this would be used.
>>
>> Suppose that I want to control the ability to create/modify privileged
>> executables on the system.  Given that SELinux already controls
>> capability usage, I can already do that by labeling privileged
>> executable with an appropriate type and controlling the ability to
>> create/modify/relabelto that type, without being concerned about the
>> suid bit.  Why do I need this check?  And if I need this check, then
>> don't I need a similar check on setting/clearing file capabilities on a
>> given file?
> 
> One other tidbit: I don't believe that this check will get applied in
> the case where a suid/sgid binary is overwritten and the suid/sgid bits
> are forcibly cleared (ATTR_FORCE), as the selinux_inode_setattr() hook
> returns immediately in that case as it must not fail.
> 
>> Last concern I have is with this check not being adequately granular
>> since it is a single check for setting or clearing the suid or sgid bit
>> of a file owned by any user, whereas it seems more security-relevant to
>> be setting the suid bit on a root-owned executable than to be clearing
>> it or to be setting the suid bit on a sds-owned executable.  I'm not
>> sure how to write a useful policy that lets users do things that are
>> harmless or of no interest while still enforcing a useful goal.
>>
>>> Signed-off-by: Eric Paris <eparis@redhat.com>
>>>
>>> ---
>>>
>>>  security/selinux/hooks.c                     |   22 ++++++++++++++++++++--
>>>  security/selinux/include/av_perm_to_string.h |    1 +
>>>  security/selinux/include/av_permissions.h    |    1 +
>>>  security/selinux/include/class_to_string.h   |    4 ++++
>>>  security/selinux/include/security.h          |    2 ++
>>>  security/selinux/selinuxfs.c                 |    3 ++-
>>>  security/selinux/ss/services.c               |    3 +++
>>>  7 files changed, 33 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>>> index 576e511..58af86a 100644
>>> --- a/security/selinux/hooks.c
>>> +++ b/security/selinux/hooks.c
>>> @@ -2659,6 +2659,8 @@ static int selinux_inode_permission(struct inode *inode, int mask)
>>>  static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>>>  {
>>>  	int rc;
>>> +	unsigned int mode = dentry->d_inode->i_mode;
>>> +	u32 av = 0;
>>>  
>>>  	rc = secondary_ops->inode_setattr(dentry, iattr);
>>>  	if (rc)
>>> @@ -2667,11 +2669,27 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>>>  	if (iattr->ia_valid & ATTR_FORCE)
>>>  		return 0;
>>>  
>>> +	/*
>>> +	 * are we changing mode?
>>> +	 * does policy support seperate suid/sgid checks?
>>> +	 * is this a regular file?
>>> +	 * do either the old inode->i_mode or the new iattr->i_mode have the
>>> +	 * suid/sgid bits set?
>>> +	 */
>>> +	if ((iattr->ia_valid & ATTR_MODE) &&
>>> +	    selinux_policycap_setsuidperm &&
>>> +	    (S_ISREG(mode)) &&
>>> +	    ((iattr->ia_mode & (S_ISUID | S_ISGID)) ||
>>> +	     (mode & (S_ISUID | S_ISGID))))
>>> +			av |= FILE__SETSUID;
>>> +
>>>  	if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
>>>  			       ATTR_ATIME_SET | ATTR_MTIME_SET))
>>> -		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
>>> +		av |= FILE__SETATTR;
>>> +	else
>>> +		av = FILE__WRITE;
>>>  
>>> -	return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
>>> +	return dentry_has_perm(current, NULL, dentry, av);
>>>  }
>>>  
>>>  static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
>>> diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
>>> index 1223b4f..c6c5c0e 100644
>>> --- a/security/selinux/include/av_perm_to_string.h
>>> +++ b/security/selinux/include/av_perm_to_string.h
>>> @@ -19,6 +19,7 @@
>>>     S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
>>>     S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
>>>     S_(SECCLASS_FILE, FILE__OPEN, "open")
>>> +   S_(SECCLASS_FILE, FILE__SETSUID, "setsuid")
>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
>>> diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
>>> index c4c5116..cd6d566 100644
>>> --- a/security/selinux/include/av_permissions.h
>>> +++ b/security/selinux/include/av_permissions.h
>>> @@ -101,6 +101,7 @@
>>>  #define FILE__ENTRYPOINT                          0x00040000UL
>>>  #define FILE__EXECMOD                             0x00080000UL
>>>  #define FILE__OPEN                                0x00100000UL
>>> +#define FILE__SETSUID                             0x00200000UL
>>>  #define LNK_FILE__IOCTL                           0x00000001UL
>>>  #define LNK_FILE__READ                            0x00000002UL
>>>  #define LNK_FILE__WRITE                           0x00000004UL
>>> diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
>>> index bd813c3..0d11270 100644
>>> --- a/security/selinux/include/class_to_string.h
>>> +++ b/security/selinux/include/class_to_string.h
>>> @@ -72,3 +72,7 @@
>>>      S_(NULL)
>>>      S_("peer")
>>>      S_("capability2")
>>> +    S_(NULL)
>>> +    S_(NULL)
>>> +    S_(NULL)
>>> +    S_(NULL)
>>> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
>>> index 7244737..a604f05 100644
>>> --- a/security/selinux/include/security.h
>>> +++ b/security/selinux/include/security.h
>>> @@ -56,12 +56,14 @@ extern int selinux_mls_enabled;
>>>  enum {
>>>  	POLICYDB_CAPABILITY_NETPEER,
>>>  	POLICYDB_CAPABILITY_OPENPERM,
>>> +	POLICYDB_CAPABILITY_SETSUIDPERM,
>>>  	__POLICYDB_CAPABILITY_MAX
>>>  };
>>>  #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
>>>  
>>>  extern int selinux_policycap_netpeer;
>>>  extern int selinux_policycap_openperm;
>>> +extern int selinux_policycap_setsuidperm;
>>>  
>>>  /*
>>>   * type_datum properties
>>> diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
>>> index 69c9dcc..26ef62f 100644
>>> --- a/security/selinux/selinuxfs.c
>>> +++ b/security/selinux/selinuxfs.c
>>> @@ -42,7 +42,8 @@
>>>  /* Policy capability filenames */
>>>  static char *policycap_names[] = {
>>>  	"network_peer_controls",
>>> -	"open_perms"
>>> +	"open_perms",
>>> +	"setsuid_perms",
>>>  };
>>>  
>>>  unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
>>> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
>>> index 343c8ab..9ecd8e7 100644
>>> --- a/security/selinux/ss/services.c
>>> +++ b/security/selinux/ss/services.c
>>> @@ -64,6 +64,7 @@ unsigned int policydb_loaded_version;
>>>  
>>>  int selinux_policycap_netpeer;
>>>  int selinux_policycap_openperm;
>>> +int selinux_policycap_setsuidperm;
>>>  
>>>  /*
>>>   * This is declared in avc.c
>>> @@ -1615,6 +1616,8 @@ static void security_load_policycaps(void)
>>>  						  POLICYDB_CAPABILITY_NETPEER);
>>>  	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
>>>  						  POLICYDB_CAPABILITY_OPENPERM);
>>> +	selinux_policycap_setsuidperm = ebitmap_get_bit(&policydb.policycaps,
>>> +						  POLICYDB_CAPABILITY_SETSUIDPERM);
>>>  }
>>>  
>>>  extern void selinux_complete_init(void);
>>>
The reason I asked for this is for the confined administrator user.

Say I am webadmin of a system.  I can run sudo to become
webadm_r:webadmin_t as UID 0.  I now want to change the permissions on a
cgi script to be executable.  If I can change it to setuid, or setgid, I
might be able to find an alternate root to executing the app with raised
privs.

I just see this as a risk, and I see little reason why a confined
administrator would even need to setuid/setgid an application.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkj43OMACgkQrlYvE4MpobMU2gCgmUv9CJojTN/f9Ivg9ZTFBdt5
LgMAoN8MvV5BJ4lsC52fdlny0lddjXJV
=5Yyx
-----END PGP SIGNATURE-----

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 18:43     ` Daniel J Walsh
@ 2008-10-17 18:53       ` Stephen Smalley
  2008-10-17 19:10         ` Daniel J Walsh
  2008-10-17 20:50         ` Daniel J Walsh
  0 siblings, 2 replies; 23+ messages in thread
From: Stephen Smalley @ 2008-10-17 18:53 UTC (permalink / raw)
  To: Daniel J Walsh; +Cc: Eric Paris, selinux, jmorris, sgrubb

On Fri, 2008-10-17 at 14:43 -0400, Daniel J Walsh wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Stephen Smalley wrote:
> > On Fri, 2008-10-17 at 12:52 -0400, Stephen Smalley wrote:
> >> On Fri, 2008-10-17 at 11:40 -0400, Eric Paris wrote:
> >>> This patch adds a new permission, setsuid, to the file class.  This
> >>> permission is checked any time a file has its attributes modified
> >>> (setattr) and the setuid or setgid bits are involved.  The purpose for
> >>> this change is to further allow selinux to confine administrative
> >>> duties.  The example explains when the permission is needed and when it
> >>> is not:
> >>>
> >>> Start with a file with chmod 0644.
> >>> chmod u+s  (0644 -> 4644) { setattr setsuid }
> >>> chmod u-r  (4644 -> 4244) { setattr setsuid }
> >>> chmod u-s  (4244 -> 0244) { setattr setsuid }
> >>> chmod u+r  (0244 -> 0644) { setattr }
> >>>
> >>> If either the starting or the final attributes will have the setuid or
> >>> setgid bits set you need this permission.
> >> I'd like to understand better how this would be used.
> >>
> >> Suppose that I want to control the ability to create/modify privileged
> >> executables on the system.  Given that SELinux already controls
> >> capability usage, I can already do that by labeling privileged
> >> executable with an appropriate type and controlling the ability to
> >> create/modify/relabelto that type, without being concerned about the
> >> suid bit.  Why do I need this check?  And if I need this check, then
> >> don't I need a similar check on setting/clearing file capabilities on a
> >> given file?
> > 
> > One other tidbit: I don't believe that this check will get applied in
> > the case where a suid/sgid binary is overwritten and the suid/sgid bits
> > are forcibly cleared (ATTR_FORCE), as the selinux_inode_setattr() hook
> > returns immediately in that case as it must not fail.
> > 
> >> Last concern I have is with this check not being adequately granular
> >> since it is a single check for setting or clearing the suid or sgid bit
> >> of a file owned by any user, whereas it seems more security-relevant to
> >> be setting the suid bit on a root-owned executable than to be clearing
> >> it or to be setting the suid bit on a sds-owned executable.  I'm not
> >> sure how to write a useful policy that lets users do things that are
> >> harmless or of no interest while still enforcing a useful goal.
> >>
> >>> Signed-off-by: Eric Paris <eparis@redhat.com>
> >>>
> >>> ---
> >>>
> >>>  security/selinux/hooks.c                     |   22 ++++++++++++++++++++--
> >>>  security/selinux/include/av_perm_to_string.h |    1 +
> >>>  security/selinux/include/av_permissions.h    |    1 +
> >>>  security/selinux/include/class_to_string.h   |    4 ++++
> >>>  security/selinux/include/security.h          |    2 ++
> >>>  security/selinux/selinuxfs.c                 |    3 ++-
> >>>  security/selinux/ss/services.c               |    3 +++
> >>>  7 files changed, 33 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> >>> index 576e511..58af86a 100644
> >>> --- a/security/selinux/hooks.c
> >>> +++ b/security/selinux/hooks.c
> >>> @@ -2659,6 +2659,8 @@ static int selinux_inode_permission(struct inode *inode, int mask)
> >>>  static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
> >>>  {
> >>>  	int rc;
> >>> +	unsigned int mode = dentry->d_inode->i_mode;
> >>> +	u32 av = 0;
> >>>  
> >>>  	rc = secondary_ops->inode_setattr(dentry, iattr);
> >>>  	if (rc)
> >>> @@ -2667,11 +2669,27 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
> >>>  	if (iattr->ia_valid & ATTR_FORCE)
> >>>  		return 0;
> >>>  
> >>> +	/*
> >>> +	 * are we changing mode?
> >>> +	 * does policy support seperate suid/sgid checks?
> >>> +	 * is this a regular file?
> >>> +	 * do either the old inode->i_mode or the new iattr->i_mode have the
> >>> +	 * suid/sgid bits set?
> >>> +	 */
> >>> +	if ((iattr->ia_valid & ATTR_MODE) &&
> >>> +	    selinux_policycap_setsuidperm &&
> >>> +	    (S_ISREG(mode)) &&
> >>> +	    ((iattr->ia_mode & (S_ISUID | S_ISGID)) ||
> >>> +	     (mode & (S_ISUID | S_ISGID))))
> >>> +			av |= FILE__SETSUID;
> >>> +
> >>>  	if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
> >>>  			       ATTR_ATIME_SET | ATTR_MTIME_SET))
> >>> -		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
> >>> +		av |= FILE__SETATTR;
> >>> +	else
> >>> +		av = FILE__WRITE;
> >>>  
> >>> -	return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
> >>> +	return dentry_has_perm(current, NULL, dentry, av);
> >>>  }
> >>>  
> >>>  static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
> >>> diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
> >>> index 1223b4f..c6c5c0e 100644
> >>> --- a/security/selinux/include/av_perm_to_string.h
> >>> +++ b/security/selinux/include/av_perm_to_string.h
> >>> @@ -19,6 +19,7 @@
> >>>     S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
> >>>     S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
> >>>     S_(SECCLASS_FILE, FILE__OPEN, "open")
> >>> +   S_(SECCLASS_FILE, FILE__SETSUID, "setsuid")
> >>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
> >>>     S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
> >>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
> >>> diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
> >>> index c4c5116..cd6d566 100644
> >>> --- a/security/selinux/include/av_permissions.h
> >>> +++ b/security/selinux/include/av_permissions.h
> >>> @@ -101,6 +101,7 @@
> >>>  #define FILE__ENTRYPOINT                          0x00040000UL
> >>>  #define FILE__EXECMOD                             0x00080000UL
> >>>  #define FILE__OPEN                                0x00100000UL
> >>> +#define FILE__SETSUID                             0x00200000UL
> >>>  #define LNK_FILE__IOCTL                           0x00000001UL
> >>>  #define LNK_FILE__READ                            0x00000002UL
> >>>  #define LNK_FILE__WRITE                           0x00000004UL
> >>> diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
> >>> index bd813c3..0d11270 100644
> >>> --- a/security/selinux/include/class_to_string.h
> >>> +++ b/security/selinux/include/class_to_string.h
> >>> @@ -72,3 +72,7 @@
> >>>      S_(NULL)
> >>>      S_("peer")
> >>>      S_("capability2")
> >>> +    S_(NULL)
> >>> +    S_(NULL)
> >>> +    S_(NULL)
> >>> +    S_(NULL)
> >>> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
> >>> index 7244737..a604f05 100644
> >>> --- a/security/selinux/include/security.h
> >>> +++ b/security/selinux/include/security.h
> >>> @@ -56,12 +56,14 @@ extern int selinux_mls_enabled;
> >>>  enum {
> >>>  	POLICYDB_CAPABILITY_NETPEER,
> >>>  	POLICYDB_CAPABILITY_OPENPERM,
> >>> +	POLICYDB_CAPABILITY_SETSUIDPERM,
> >>>  	__POLICYDB_CAPABILITY_MAX
> >>>  };
> >>>  #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
> >>>  
> >>>  extern int selinux_policycap_netpeer;
> >>>  extern int selinux_policycap_openperm;
> >>> +extern int selinux_policycap_setsuidperm;
> >>>  
> >>>  /*
> >>>   * type_datum properties
> >>> diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
> >>> index 69c9dcc..26ef62f 100644
> >>> --- a/security/selinux/selinuxfs.c
> >>> +++ b/security/selinux/selinuxfs.c
> >>> @@ -42,7 +42,8 @@
> >>>  /* Policy capability filenames */
> >>>  static char *policycap_names[] = {
> >>>  	"network_peer_controls",
> >>> -	"open_perms"
> >>> +	"open_perms",
> >>> +	"setsuid_perms",
> >>>  };
> >>>  
> >>>  unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
> >>> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> >>> index 343c8ab..9ecd8e7 100644
> >>> --- a/security/selinux/ss/services.c
> >>> +++ b/security/selinux/ss/services.c
> >>> @@ -64,6 +64,7 @@ unsigned int policydb_loaded_version;
> >>>  
> >>>  int selinux_policycap_netpeer;
> >>>  int selinux_policycap_openperm;
> >>> +int selinux_policycap_setsuidperm;
> >>>  
> >>>  /*
> >>>   * This is declared in avc.c
> >>> @@ -1615,6 +1616,8 @@ static void security_load_policycaps(void)
> >>>  						  POLICYDB_CAPABILITY_NETPEER);
> >>>  	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
> >>>  						  POLICYDB_CAPABILITY_OPENPERM);
> >>> +	selinux_policycap_setsuidperm = ebitmap_get_bit(&policydb.policycaps,
> >>> +						  POLICYDB_CAPABILITY_SETSUIDPERM);
> >>>  }
> >>>  
> >>>  extern void selinux_complete_init(void);
> >>>
> The reason I asked for this is for the confined administrator user.
> 
> Say I am webadmin of a system.  I can run sudo to become
> webadm_r:webadmin_t as UID 0.  I now want to change the permissions on a
> cgi script to be executable.  If I can change it to setuid, or setgid, I
> might be able to find an alternate root to executing the app with raised
> privs.
> 
> I just see this as a risk, and I see little reason why a confined
> administrator would even need to setuid/setgid an application.

Well, as I noted when this came up as an RFC a year ago, the fact that
they can create a setuid program doesn't mean that they can exercise any
capabilities since we control that based on domain.  And rather than
preventing them from setting the suid bit, it might be more useful to
prevent them from executing a setuid program (regardless of who made it
setuid) or letting it execute but not changing its uid in that case
(just as we do under ptrace).

http://marc.info/?l=selinux&m=119013530120434&w=2

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 18:53       ` Stephen Smalley
@ 2008-10-17 19:10         ` Daniel J Walsh
  2008-10-17 19:39           ` Stephen Smalley
  2008-10-17 20:50         ` Daniel J Walsh
  1 sibling, 1 reply; 23+ messages in thread
From: Daniel J Walsh @ 2008-10-17 19:10 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Eric Paris, selinux, jmorris, sgrubb

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Stephen Smalley wrote:
> On Fri, 2008-10-17 at 14:43 -0400, Daniel J Walsh wrote:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>> Stephen Smalley wrote:
>>> On Fri, 2008-10-17 at 12:52 -0400, Stephen Smalley wrote:
>>>> On Fri, 2008-10-17 at 11:40 -0400, Eric Paris wrote:
>>>>> This patch adds a new permission, setsuid, to the file class.  This
>>>>> permission is checked any time a file has its attributes modified
>>>>> (setattr) and the setuid or setgid bits are involved.  The purpose for
>>>>> this change is to further allow selinux to confine administrative
>>>>> duties.  The example explains when the permission is needed and when it
>>>>> is not:
>>>>>
>>>>> Start with a file with chmod 0644.
>>>>> chmod u+s  (0644 -> 4644) { setattr setsuid }
>>>>> chmod u-r  (4644 -> 4244) { setattr setsuid }
>>>>> chmod u-s  (4244 -> 0244) { setattr setsuid }
>>>>> chmod u+r  (0244 -> 0644) { setattr }
>>>>>
>>>>> If either the starting or the final attributes will have the setuid or
>>>>> setgid bits set you need this permission.
>>>> I'd like to understand better how this would be used.
>>>>
>>>> Suppose that I want to control the ability to create/modify privileged
>>>> executables on the system.  Given that SELinux already controls
>>>> capability usage, I can already do that by labeling privileged
>>>> executable with an appropriate type and controlling the ability to
>>>> create/modify/relabelto that type, without being concerned about the
>>>> suid bit.  Why do I need this check?  And if I need this check, then
>>>> don't I need a similar check on setting/clearing file capabilities on a
>>>> given file?
>>> One other tidbit: I don't believe that this check will get applied in
>>> the case where a suid/sgid binary is overwritten and the suid/sgid bits
>>> are forcibly cleared (ATTR_FORCE), as the selinux_inode_setattr() hook
>>> returns immediately in that case as it must not fail.
>>>
>>>> Last concern I have is with this check not being adequately granular
>>>> since it is a single check for setting or clearing the suid or sgid bit
>>>> of a file owned by any user, whereas it seems more security-relevant to
>>>> be setting the suid bit on a root-owned executable than to be clearing
>>>> it or to be setting the suid bit on a sds-owned executable.  I'm not
>>>> sure how to write a useful policy that lets users do things that are
>>>> harmless or of no interest while still enforcing a useful goal.
>>>>
>>>>> Signed-off-by: Eric Paris <eparis@redhat.com>
>>>>>
>>>>> ---
>>>>>
>>>>>  security/selinux/hooks.c                     |   22 ++++++++++++++++++++--
>>>>>  security/selinux/include/av_perm_to_string.h |    1 +
>>>>>  security/selinux/include/av_permissions.h    |    1 +
>>>>>  security/selinux/include/class_to_string.h   |    4 ++++
>>>>>  security/selinux/include/security.h          |    2 ++
>>>>>  security/selinux/selinuxfs.c                 |    3 ++-
>>>>>  security/selinux/ss/services.c               |    3 +++
>>>>>  7 files changed, 33 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>>>>> index 576e511..58af86a 100644
>>>>> --- a/security/selinux/hooks.c
>>>>> +++ b/security/selinux/hooks.c
>>>>> @@ -2659,6 +2659,8 @@ static int selinux_inode_permission(struct inode *inode, int mask)
>>>>>  static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>>>>>  {
>>>>>  	int rc;
>>>>> +	unsigned int mode = dentry->d_inode->i_mode;
>>>>> +	u32 av = 0;
>>>>>  
>>>>>  	rc = secondary_ops->inode_setattr(dentry, iattr);
>>>>>  	if (rc)
>>>>> @@ -2667,11 +2669,27 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>>>>>  	if (iattr->ia_valid & ATTR_FORCE)
>>>>>  		return 0;
>>>>>  
>>>>> +	/*
>>>>> +	 * are we changing mode?
>>>>> +	 * does policy support seperate suid/sgid checks?
>>>>> +	 * is this a regular file?
>>>>> +	 * do either the old inode->i_mode or the new iattr->i_mode have the
>>>>> +	 * suid/sgid bits set?
>>>>> +	 */
>>>>> +	if ((iattr->ia_valid & ATTR_MODE) &&
>>>>> +	    selinux_policycap_setsuidperm &&
>>>>> +	    (S_ISREG(mode)) &&
>>>>> +	    ((iattr->ia_mode & (S_ISUID | S_ISGID)) ||
>>>>> +	     (mode & (S_ISUID | S_ISGID))))
>>>>> +			av |= FILE__SETSUID;
>>>>> +
>>>>>  	if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
>>>>>  			       ATTR_ATIME_SET | ATTR_MTIME_SET))
>>>>> -		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
>>>>> +		av |= FILE__SETATTR;
>>>>> +	else
>>>>> +		av = FILE__WRITE;
>>>>>  
>>>>> -	return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
>>>>> +	return dentry_has_perm(current, NULL, dentry, av);
>>>>>  }
>>>>>  
>>>>>  static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
>>>>> diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
>>>>> index 1223b4f..c6c5c0e 100644
>>>>> --- a/security/selinux/include/av_perm_to_string.h
>>>>> +++ b/security/selinux/include/av_perm_to_string.h
>>>>> @@ -19,6 +19,7 @@
>>>>>     S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
>>>>>     S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
>>>>>     S_(SECCLASS_FILE, FILE__OPEN, "open")
>>>>> +   S_(SECCLASS_FILE, FILE__SETSUID, "setsuid")
>>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
>>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
>>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
>>>>> diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
>>>>> index c4c5116..cd6d566 100644
>>>>> --- a/security/selinux/include/av_permissions.h
>>>>> +++ b/security/selinux/include/av_permissions.h
>>>>> @@ -101,6 +101,7 @@
>>>>>  #define FILE__ENTRYPOINT                          0x00040000UL
>>>>>  #define FILE__EXECMOD                             0x00080000UL
>>>>>  #define FILE__OPEN                                0x00100000UL
>>>>> +#define FILE__SETSUID                             0x00200000UL
>>>>>  #define LNK_FILE__IOCTL                           0x00000001UL
>>>>>  #define LNK_FILE__READ                            0x00000002UL
>>>>>  #define LNK_FILE__WRITE                           0x00000004UL
>>>>> diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
>>>>> index bd813c3..0d11270 100644
>>>>> --- a/security/selinux/include/class_to_string.h
>>>>> +++ b/security/selinux/include/class_to_string.h
>>>>> @@ -72,3 +72,7 @@
>>>>>      S_(NULL)
>>>>>      S_("peer")
>>>>>      S_("capability2")
>>>>> +    S_(NULL)
>>>>> +    S_(NULL)
>>>>> +    S_(NULL)
>>>>> +    S_(NULL)
>>>>> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
>>>>> index 7244737..a604f05 100644
>>>>> --- a/security/selinux/include/security.h
>>>>> +++ b/security/selinux/include/security.h
>>>>> @@ -56,12 +56,14 @@ extern int selinux_mls_enabled;
>>>>>  enum {
>>>>>  	POLICYDB_CAPABILITY_NETPEER,
>>>>>  	POLICYDB_CAPABILITY_OPENPERM,
>>>>> +	POLICYDB_CAPABILITY_SETSUIDPERM,
>>>>>  	__POLICYDB_CAPABILITY_MAX
>>>>>  };
>>>>>  #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
>>>>>  
>>>>>  extern int selinux_policycap_netpeer;
>>>>>  extern int selinux_policycap_openperm;
>>>>> +extern int selinux_policycap_setsuidperm;
>>>>>  
>>>>>  /*
>>>>>   * type_datum properties
>>>>> diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
>>>>> index 69c9dcc..26ef62f 100644
>>>>> --- a/security/selinux/selinuxfs.c
>>>>> +++ b/security/selinux/selinuxfs.c
>>>>> @@ -42,7 +42,8 @@
>>>>>  /* Policy capability filenames */
>>>>>  static char *policycap_names[] = {
>>>>>  	"network_peer_controls",
>>>>> -	"open_perms"
>>>>> +	"open_perms",
>>>>> +	"setsuid_perms",
>>>>>  };
>>>>>  
>>>>>  unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
>>>>> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
>>>>> index 343c8ab..9ecd8e7 100644
>>>>> --- a/security/selinux/ss/services.c
>>>>> +++ b/security/selinux/ss/services.c
>>>>> @@ -64,6 +64,7 @@ unsigned int policydb_loaded_version;
>>>>>  
>>>>>  int selinux_policycap_netpeer;
>>>>>  int selinux_policycap_openperm;
>>>>> +int selinux_policycap_setsuidperm;
>>>>>  
>>>>>  /*
>>>>>   * This is declared in avc.c
>>>>> @@ -1615,6 +1616,8 @@ static void security_load_policycaps(void)
>>>>>  						  POLICYDB_CAPABILITY_NETPEER);
>>>>>  	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
>>>>>  						  POLICYDB_CAPABILITY_OPENPERM);
>>>>> +	selinux_policycap_setsuidperm = ebitmap_get_bit(&policydb.policycaps,
>>>>> +						  POLICYDB_CAPABILITY_SETSUIDPERM);
>>>>>  }
>>>>>  
>>>>>  extern void selinux_complete_init(void);
>>>>>
>> The reason I asked for this is for the confined administrator user.
>>
>> Say I am webadmin of a system.  I can run sudo to become
>> webadm_r:webadmin_t as UID 0.  I now want to change the permissions on a
>> cgi script to be executable.  If I can change it to setuid, or setgid, I
>> might be able to find an alternate root to executing the app with raised
>> privs.
>>
>> I just see this as a risk, and I see little reason why a confined
>> administrator would even need to setuid/setgid an application.
> 
> Well, as I noted when this came up as an RFC a year ago, the fact that
> they can create a setuid program doesn't mean that they can exercise any
> capabilities since we control that based on domain.  And rather than
> preventing them from setting the suid bit, it might be more useful to
> prevent them from executing a setuid program (regardless of who made it
> setuid) or letting it execute but not changing its uid in that case
> (just as we do under ptrace).
> 
> http://marc.info/?l=selinux&m=119013530120434&w=2
> 
But I see the problem not with webadm_t executing the setuid app, but
potentially another domain that he can trigger.  Say apache or samba or
ftp.  If one of these apps has "setuid" capability they could execute
the setuid app and potentially escalate privs.

sesearch --allow | grep setuid | wc
WARNING: This policy contained disabled aliases; they have been removed.
    197    3947   33797

197 domains have the ability to setuid, if the bad admin figures a way
to get one of these confined domains to run his application, he might be
able to do something evil.



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkj44zMACgkQrlYvE4MpobNj+QCfaQaoJ11g12D5nTHEOBhp1jz8
enwAn2ddpQbSrXDq1aVWbg4MeHL0bf1w
=5aec
-----END PGP SIGNATURE-----

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 19:10         ` Daniel J Walsh
@ 2008-10-17 19:39           ` Stephen Smalley
  2008-10-17 20:04             ` Eric Paris
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2008-10-17 19:39 UTC (permalink / raw)
  To: Daniel J Walsh; +Cc: Eric Paris, selinux, jmorris, sgrubb

On Fri, 2008-10-17 at 15:10 -0400, Daniel J Walsh wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Stephen Smalley wrote:
> > On Fri, 2008-10-17 at 14:43 -0400, Daniel J Walsh wrote:
> >> -----BEGIN PGP SIGNED MESSAGE-----
> >> Hash: SHA1
> >>
> >> Stephen Smalley wrote:
> >>> On Fri, 2008-10-17 at 12:52 -0400, Stephen Smalley wrote:
> >>>> On Fri, 2008-10-17 at 11:40 -0400, Eric Paris wrote:
> >>>>> This patch adds a new permission, setsuid, to the file class.  This
> >>>>> permission is checked any time a file has its attributes modified
> >>>>> (setattr) and the setuid or setgid bits are involved.  The purpose for
> >>>>> this change is to further allow selinux to confine administrative
> >>>>> duties.  The example explains when the permission is needed and when it
> >>>>> is not:
> >>>>>
> >>>>> Start with a file with chmod 0644.
> >>>>> chmod u+s  (0644 -> 4644) { setattr setsuid }
> >>>>> chmod u-r  (4644 -> 4244) { setattr setsuid }
> >>>>> chmod u-s  (4244 -> 0244) { setattr setsuid }
> >>>>> chmod u+r  (0244 -> 0644) { setattr }
> >>>>>
> >>>>> If either the starting or the final attributes will have the setuid or
> >>>>> setgid bits set you need this permission.
> >>>> I'd like to understand better how this would be used.
> >>>>
> >>>> Suppose that I want to control the ability to create/modify privileged
> >>>> executables on the system.  Given that SELinux already controls
> >>>> capability usage, I can already do that by labeling privileged
> >>>> executable with an appropriate type and controlling the ability to
> >>>> create/modify/relabelto that type, without being concerned about the
> >>>> suid bit.  Why do I need this check?  And if I need this check, then
> >>>> don't I need a similar check on setting/clearing file capabilities on a
> >>>> given file?
> >>> One other tidbit: I don't believe that this check will get applied in
> >>> the case where a suid/sgid binary is overwritten and the suid/sgid bits
> >>> are forcibly cleared (ATTR_FORCE), as the selinux_inode_setattr() hook
> >>> returns immediately in that case as it must not fail.
> >>>
> >>>> Last concern I have is with this check not being adequately granular
> >>>> since it is a single check for setting or clearing the suid or sgid bit
> >>>> of a file owned by any user, whereas it seems more security-relevant to
> >>>> be setting the suid bit on a root-owned executable than to be clearing
> >>>> it or to be setting the suid bit on a sds-owned executable.  I'm not
> >>>> sure how to write a useful policy that lets users do things that are
> >>>> harmless or of no interest while still enforcing a useful goal.
> >>>>
> >>>>> Signed-off-by: Eric Paris <eparis@redhat.com>
> >>>>>
> >>>>> ---
> >>>>>
> >>>>>  security/selinux/hooks.c                     |   22 ++++++++++++++++++++--
> >>>>>  security/selinux/include/av_perm_to_string.h |    1 +
> >>>>>  security/selinux/include/av_permissions.h    |    1 +
> >>>>>  security/selinux/include/class_to_string.h   |    4 ++++
> >>>>>  security/selinux/include/security.h          |    2 ++
> >>>>>  security/selinux/selinuxfs.c                 |    3 ++-
> >>>>>  security/selinux/ss/services.c               |    3 +++
> >>>>>  7 files changed, 33 insertions(+), 3 deletions(-)
> >>>>>
> >>>>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> >>>>> index 576e511..58af86a 100644
> >>>>> --- a/security/selinux/hooks.c
> >>>>> +++ b/security/selinux/hooks.c
> >>>>> @@ -2659,6 +2659,8 @@ static int selinux_inode_permission(struct inode *inode, int mask)
> >>>>>  static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
> >>>>>  {
> >>>>>  	int rc;
> >>>>> +	unsigned int mode = dentry->d_inode->i_mode;
> >>>>> +	u32 av = 0;
> >>>>>  
> >>>>>  	rc = secondary_ops->inode_setattr(dentry, iattr);
> >>>>>  	if (rc)
> >>>>> @@ -2667,11 +2669,27 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
> >>>>>  	if (iattr->ia_valid & ATTR_FORCE)
> >>>>>  		return 0;
> >>>>>  
> >>>>> +	/*
> >>>>> +	 * are we changing mode?
> >>>>> +	 * does policy support seperate suid/sgid checks?
> >>>>> +	 * is this a regular file?
> >>>>> +	 * do either the old inode->i_mode or the new iattr->i_mode have the
> >>>>> +	 * suid/sgid bits set?
> >>>>> +	 */
> >>>>> +	if ((iattr->ia_valid & ATTR_MODE) &&
> >>>>> +	    selinux_policycap_setsuidperm &&
> >>>>> +	    (S_ISREG(mode)) &&
> >>>>> +	    ((iattr->ia_mode & (S_ISUID | S_ISGID)) ||
> >>>>> +	     (mode & (S_ISUID | S_ISGID))))
> >>>>> +			av |= FILE__SETSUID;
> >>>>> +
> >>>>>  	if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
> >>>>>  			       ATTR_ATIME_SET | ATTR_MTIME_SET))
> >>>>> -		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
> >>>>> +		av |= FILE__SETATTR;
> >>>>> +	else
> >>>>> +		av = FILE__WRITE;
> >>>>>  
> >>>>> -	return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
> >>>>> +	return dentry_has_perm(current, NULL, dentry, av);
> >>>>>  }
> >>>>>  
> >>>>>  static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
> >>>>> diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
> >>>>> index 1223b4f..c6c5c0e 100644
> >>>>> --- a/security/selinux/include/av_perm_to_string.h
> >>>>> +++ b/security/selinux/include/av_perm_to_string.h
> >>>>> @@ -19,6 +19,7 @@
> >>>>>     S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
> >>>>>     S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
> >>>>>     S_(SECCLASS_FILE, FILE__OPEN, "open")
> >>>>> +   S_(SECCLASS_FILE, FILE__SETSUID, "setsuid")
> >>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
> >>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
> >>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
> >>>>> diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
> >>>>> index c4c5116..cd6d566 100644
> >>>>> --- a/security/selinux/include/av_permissions.h
> >>>>> +++ b/security/selinux/include/av_permissions.h
> >>>>> @@ -101,6 +101,7 @@
> >>>>>  #define FILE__ENTRYPOINT                          0x00040000UL
> >>>>>  #define FILE__EXECMOD                             0x00080000UL
> >>>>>  #define FILE__OPEN                                0x00100000UL
> >>>>> +#define FILE__SETSUID                             0x00200000UL
> >>>>>  #define LNK_FILE__IOCTL                           0x00000001UL
> >>>>>  #define LNK_FILE__READ                            0x00000002UL
> >>>>>  #define LNK_FILE__WRITE                           0x00000004UL
> >>>>> diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
> >>>>> index bd813c3..0d11270 100644
> >>>>> --- a/security/selinux/include/class_to_string.h
> >>>>> +++ b/security/selinux/include/class_to_string.h
> >>>>> @@ -72,3 +72,7 @@
> >>>>>      S_(NULL)
> >>>>>      S_("peer")
> >>>>>      S_("capability2")
> >>>>> +    S_(NULL)
> >>>>> +    S_(NULL)
> >>>>> +    S_(NULL)
> >>>>> +    S_(NULL)
> >>>>> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
> >>>>> index 7244737..a604f05 100644
> >>>>> --- a/security/selinux/include/security.h
> >>>>> +++ b/security/selinux/include/security.h
> >>>>> @@ -56,12 +56,14 @@ extern int selinux_mls_enabled;
> >>>>>  enum {
> >>>>>  	POLICYDB_CAPABILITY_NETPEER,
> >>>>>  	POLICYDB_CAPABILITY_OPENPERM,
> >>>>> +	POLICYDB_CAPABILITY_SETSUIDPERM,
> >>>>>  	__POLICYDB_CAPABILITY_MAX
> >>>>>  };
> >>>>>  #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
> >>>>>  
> >>>>>  extern int selinux_policycap_netpeer;
> >>>>>  extern int selinux_policycap_openperm;
> >>>>> +extern int selinux_policycap_setsuidperm;
> >>>>>  
> >>>>>  /*
> >>>>>   * type_datum properties
> >>>>> diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
> >>>>> index 69c9dcc..26ef62f 100644
> >>>>> --- a/security/selinux/selinuxfs.c
> >>>>> +++ b/security/selinux/selinuxfs.c
> >>>>> @@ -42,7 +42,8 @@
> >>>>>  /* Policy capability filenames */
> >>>>>  static char *policycap_names[] = {
> >>>>>  	"network_peer_controls",
> >>>>> -	"open_perms"
> >>>>> +	"open_perms",
> >>>>> +	"setsuid_perms",
> >>>>>  };
> >>>>>  
> >>>>>  unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
> >>>>> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> >>>>> index 343c8ab..9ecd8e7 100644
> >>>>> --- a/security/selinux/ss/services.c
> >>>>> +++ b/security/selinux/ss/services.c
> >>>>> @@ -64,6 +64,7 @@ unsigned int policydb_loaded_version;
> >>>>>  
> >>>>>  int selinux_policycap_netpeer;
> >>>>>  int selinux_policycap_openperm;
> >>>>> +int selinux_policycap_setsuidperm;
> >>>>>  
> >>>>>  /*
> >>>>>   * This is declared in avc.c
> >>>>> @@ -1615,6 +1616,8 @@ static void security_load_policycaps(void)
> >>>>>  						  POLICYDB_CAPABILITY_NETPEER);
> >>>>>  	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
> >>>>>  						  POLICYDB_CAPABILITY_OPENPERM);
> >>>>> +	selinux_policycap_setsuidperm = ebitmap_get_bit(&policydb.policycaps,
> >>>>> +						  POLICYDB_CAPABILITY_SETSUIDPERM);
> >>>>>  }
> >>>>>  
> >>>>>  extern void selinux_complete_init(void);
> >>>>>
> >> The reason I asked for this is for the confined administrator user.
> >>
> >> Say I am webadmin of a system.  I can run sudo to become
> >> webadm_r:webadmin_t as UID 0.  I now want to change the permissions on a
> >> cgi script to be executable.  If I can change it to setuid, or setgid, I
> >> might be able to find an alternate root to executing the app with raised
> >> privs.
> >>
> >> I just see this as a risk, and I see little reason why a confined
> >> administrator would even need to setuid/setgid an application.
> > 
> > Well, as I noted when this came up as an RFC a year ago, the fact that
> > they can create a setuid program doesn't mean that they can exercise any
> > capabilities since we control that based on domain.  And rather than
> > preventing them from setting the suid bit, it might be more useful to
> > prevent them from executing a setuid program (regardless of who made it
> > setuid) or letting it execute but not changing its uid in that case
> > (just as we do under ptrace).
> > 
> > http://marc.info/?l=selinux&m=119013530120434&w=2
> > 
> But I see the problem not with webadm_t executing the setuid app, but
> potentially another domain that he can trigger.  Say apache or samba or
> ftp.  If one of these apps has "setuid" capability they could execute
> the setuid app and potentially escalate privs.
> 
> sesearch --allow | grep setuid | wc
> WARNING: This policy contained disabled aliases; they have been removed.
>     197    3947   33797
> 
> 197 domains have the ability to setuid, if the bad admin figures a way
> to get one of these confined domains to run his application, he might be
> able to do something evil.

I don't follow the above.  First, the CAP_SETUID capability controls the
ability to use set*uid() system calls, not to execute setuid binaries
(aside from a special case for shared state).  Second, if some other
confined domain executes a setuid binary created by this user, it is
still limited by the permissions granted to that original confined
domain as far as SELinux is concerned.

Going back to your earlier explanation though, it sounds like you want
to prevent a user from creating their own entrypoint programs into their
own user identity.  In that case, I don't see why you care about
clearing the bit or changing other parts of the mode.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 19:39           ` Stephen Smalley
@ 2008-10-17 20:04             ` Eric Paris
  2008-10-17 20:09               ` Stephen Smalley
  0 siblings, 1 reply; 23+ messages in thread
From: Eric Paris @ 2008-10-17 20:04 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Daniel J Walsh, selinux, jmorris, sgrubb

On Fri, 2008-10-17 at 15:39 -0400, Stephen Smalley wrote:

> I don't follow the above.  First, the CAP_SETUID capability controls the
> ability to use set*uid() system calls, not to execute setuid binaries
> (aside from a special case for shared state).  Second, if some other
> confined domain executes a setuid binary created by this user, it is
> still limited by the permissions granted to that original confined
> domain as far as SELinux is concerned.

He's saying there are almost 200 domains that can run setuid apps.
Limiting the number of domains that can create new setuid apps limits
the number of places that these domains can go.  Clearly they are all
still confined to their domain and whatever it allows, but allowing them
to gain root priveledges may give them the ability to attack other parts
of the system normally controlled by dac.  This certainly doesn't lessen
the MAC confinement.  Lets assume an audited system in which we are
certain the only suid app untrusted users are allowed to run is ping.
So the users have the right to run suid apps.  They are protected from
each other by DAC.

Confined webadmin writes a program which is clears out other users
public_html when they get a spurious DMCA takedown notice.  He then
(because he is a lazy bumbling idiot) makes his script suid so he does
not have to go into his confined webadmin account constantly to delete
users webpages.

Normal DAC protects user2 from being attacked by user1.  Because of the
bumbling incompetance of confined webadmin user1 can now use this setuid
app to do things which he is allow by selinux policy but denied by
normal DAC permissions.

Why did webadmin need to make a setuid app to begin with?  file caps are
already protected by CAP_SETFCAP.  Lets assume system policy says that
su should not be setuid.  Should the webadmin really be allowed to
easily override that system policy because he wants to use su - to get
to his confined domain instead of sudo?  She bumbling idiot really be
allowed to say add o+x to su - when the system policy only really wanted
group wheel to be able to run su?  Should the bumbling idiot be able to
remove the suid flag from a program and not be able to fix it?

I think there are some real gains that can be made by limiting how
confined admins or untrusted users can deal with suid apps.

I'd probably be inclined to add changing the uid/gid/other things that
clear setuid to be things which require this permission.  I don't see a
reason to allow my webadmin to chown su to himself...

-Eric


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 20:04             ` Eric Paris
@ 2008-10-17 20:09               ` Stephen Smalley
  2008-10-17 20:38                 ` Eric Paris
  2008-10-17 21:18                 ` Daniel J Walsh
  0 siblings, 2 replies; 23+ messages in thread
From: Stephen Smalley @ 2008-10-17 20:09 UTC (permalink / raw)
  To: Eric Paris; +Cc: Daniel J Walsh, selinux, jmorris, sgrubb

On Fri, 2008-10-17 at 16:04 -0400, Eric Paris wrote:
> On Fri, 2008-10-17 at 15:39 -0400, Stephen Smalley wrote:
> 
> > I don't follow the above.  First, the CAP_SETUID capability controls the
> > ability to use set*uid() system calls, not to execute setuid binaries
> > (aside from a special case for shared state).  Second, if some other
> > confined domain executes a setuid binary created by this user, it is
> > still limited by the permissions granted to that original confined
> > domain as far as SELinux is concerned.
> 
> He's saying there are almost 200 domains that can run setuid apps.

As I said, CAP_SETUID isn't about whether or not you can run a setuid
app.  You can do that without CAP_SETUID.  Obviously since a normal
unprivileged user shell can run a setuid program in the first place.

> Limiting the number of domains that can create new setuid apps limits
> the number of places that these domains can go.  Clearly they are all
> still confined to their domain and whatever it allows, but allowing them
> to gain root priveledges may give them the ability to attack other parts

Wait - how did they gain root privileges?  root privileges are
capabilities, and we control capabilities based on domain.

> of the system normally controlled by dac.  This certainly doesn't lessen
> the MAC confinement.  Lets assume an audited system in which we are
> certain the only suid app untrusted users are allowed to run is ping.
> So the users have the right to run suid apps.  They are protected from
> each other by DAC.
> 
> Confined webadmin writes a program which is clears out other users
> public_html when they get a spurious DMCA takedown notice.  He then
> (because he is a lazy bumbling idiot) makes his script suid so he does
> not have to go into his confined webadmin account constantly to delete
> users webpages.

He could also make a daemon that runs under his uid and accepts commands
via local socket.

> Normal DAC protects user2 from being attacked by user1.  Because of the
> bumbling incompetance of confined webadmin user1 can now use this setuid
> app to do things which he is allow by selinux policy but denied by
> normal DAC permissions.
> 
> Why did webadmin need to make a setuid app to begin with?  file caps are
> already protected by CAP_SETFCAP.  Lets assume system policy says that
> su should not be setuid.  Should the webadmin really be allowed to
> easily override that system policy because he wants to use su - to get
> to his confined domain instead of sudo?

He can't get to his confined domain via some other program unless policy
says he can.  He can only get to some other uid that way.

>   She bumbling idiot really be
> allowed to say add o+x to su - when the system policy only really wanted
> group wheel to be able to run su?  Should the bumbling idiot be able to
> remove the suid flag from a program and not be able to fix it?
> 
> I think there are some real gains that can be made by limiting how
> confined admins or untrusted users can deal with suid apps.
> 
> I'd probably be inclined to add changing the uid/gid/other things that
> clear setuid to be things which require this permission.  I don't see a
> reason to allow my webadmin to chown su to himself...

He can't do that unless he owns su (or that itself is subject to
fowner).  And chown'ing or writing to a suid app clears the suid bit
forcibly. 

Come on, guys, you can do better.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 20:09               ` Stephen Smalley
@ 2008-10-17 20:38                 ` Eric Paris
  2008-10-17 20:49                   ` Eric Paris
  2008-10-20 12:30                   ` Stephen Smalley
  2008-10-17 21:18                 ` Daniel J Walsh
  1 sibling, 2 replies; 23+ messages in thread
From: Eric Paris @ 2008-10-17 20:38 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Daniel J Walsh, selinux, jmorris, sgrubb

On Fri, 2008-10-17 at 16:09 -0400, Stephen Smalley wrote:
> On Fri, 2008-10-17 at 16:04 -0400, Eric Paris wrote:

> > of the system normally controlled by dac.  This certainly doesn't lessen
> > the MAC confinement.  Lets assume an audited system in which we are
> > certain the only suid app untrusted users are allowed to run is ping.
> > So the users have the right to run suid apps.  They are protected from
> > each other by DAC.
> > 
> > Confined webadmin writes a program which is clears out other users
> > public_html when they get a spurious DMCA takedown notice.  He then
> > (because he is a lazy bumbling idiot) makes his script suid so he does
> > not have to go into his confined webadmin account constantly to delete
> > users webpages.
> 
> He could also make a daemon that runs under his uid and accepts commands
> via local socket.

I think this is our main point of contention.  I'm not making strong
claims about the uncircumventable nature of things.  But, you aren't
allowed to on one hand claim this is useless because policy is perfect
and on the other talk about how to circumvent this protection based on
what would have to be a terrible confinement of your webadmin.  I've yet
to see a confined admin that could do many useful things without having
some method to escape the confinement.  Just because it isn't perfect
doesn't mean it's useless or even a bad idea.

Anyway, I'm not arguing this is going to provide greater MAC confinement
and I'm not able to describe security goals in terms of MAC domains.
I'm merely stating that a SELinux confined admin is easily able change
DAC security policy as defined by an organization.  Yes, DAC sercurity
policy that I'm talking about is mathmatically provable and that's the
part that I'm sure you initially reject, but it doesn't make it
pointless or even detractive. 

> > Normal DAC protects user2 from being attacked by user1.  Because of the
> > bumbling incompetance of confined webadmin user1 can now use this setuid
> > app to do things which he is allow by selinux policy but denied by
> > normal DAC permissions.
> > 
> > Why did webadmin need to make a setuid app to begin with?  file caps are
> > already protected by CAP_SETFCAP.  Lets assume system policy says that
> > su should not be setuid.  Should the webadmin really be allowed to
> > easily override that system policy because he wants to use su - to get
> > to his confined domain instead of sudo?
> 
> He can't get to his confined domain via some other program unless policy
> says he can.  He can only get to some other uid that way.

Confined domain was the wrong word.  Absolutely.  Let me reword.
"should the webadmin really be allowed to easily override that system
policy because he wasnts to use su - to get to his admin account instead
of sudo" ??

Things like user seperation are the responsibility of DAC in the real
world.  Hardening DAC enforcement should be one of our goals.

> >   She bumbling idiot really be
> > allowed to say add o+x to su - when the system policy only really wanted
> > group wheel to be able to run su?  Should the bumbling idiot be able to
> > remove the suid flag from a program and not be able to fix it?
> > 
> > I think there are some real gains that can be made by limiting how
> > confined admins or untrusted users can deal with suid apps.
> > 
> > I'd probably be inclined to add changing the uid/gid/other things that
> > clear setuid to be things which require this permission.  I don't see a
> > reason to allow my webadmin to chown su to himself...
> 
> He can't do that unless he owns su (or that itself is subject to
> fowner).  And chown'ing or writing to a suid app clears the suid bit
> forcibly.

Obivously his 'web admin' job is going to require root access.  So he
would be perfectly capable of calling chown reguser:reguser /sbin/su.
(I'm not in this particular example discussing the usefullness of the
activity.)  And thats exactly my point.  chowning is going to clear the
suid.  Since suid is set I claim that clearing that bit is against the
DAC security policy and thus chown should be forbidden as well.  My
current patch doesn't do that but I said I'd be inclined to add it.

> Come on, guys, you can do better.

Come on, Stephen, exaplin why hardening systems against confined admins
being able to override DAC system security policies is a bad idea...

-Eric


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 20:38                 ` Eric Paris
@ 2008-10-17 20:49                   ` Eric Paris
  2008-10-20 12:30                   ` Stephen Smalley
  1 sibling, 0 replies; 23+ messages in thread
From: Eric Paris @ 2008-10-17 20:49 UTC (permalink / raw)
  To: Eric Paris; +Cc: Stephen Smalley, Daniel J Walsh, selinux, jmorris, sgrubb

FAIL ALERT!

On Fri, Oct 17, 2008 at 4:38 PM, Eric Paris <eparis@redhat.com> wrote:
Yes, DAC sercurity
> policy that I'm talking about is !!NOT!!! mathmatically provable and that's the
> part that I'm sure you initially reject, but it doesn't make it
> pointless or even detractive.

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 18:53       ` Stephen Smalley
  2008-10-17 19:10         ` Daniel J Walsh
@ 2008-10-17 20:50         ` Daniel J Walsh
  2008-10-20 12:26           ` Stephen Smalley
  1 sibling, 1 reply; 23+ messages in thread
From: Daniel J Walsh @ 2008-10-17 20:50 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Eric Paris, selinux, jmorris, sgrubb

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Stephen Smalley wrote:
> On Fri, 2008-10-17 at 14:43 -0400, Daniel J Walsh wrote:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>> Stephen Smalley wrote:
>>> On Fri, 2008-10-17 at 12:52 -0400, Stephen Smalley wrote:
>>>> On Fri, 2008-10-17 at 11:40 -0400, Eric Paris wrote:
>>>>> This patch adds a new permission, setsuid, to the file class.  This
>>>>> permission is checked any time a file has its attributes modified
>>>>> (setattr) and the setuid or setgid bits are involved.  The purpose for
>>>>> this change is to further allow selinux to confine administrative
>>>>> duties.  The example explains when the permission is needed and when it
>>>>> is not:
>>>>>
>>>>> Start with a file with chmod 0644.
>>>>> chmod u+s  (0644 -> 4644) { setattr setsuid }
>>>>> chmod u-r  (4644 -> 4244) { setattr setsuid }
>>>>> chmod u-s  (4244 -> 0244) { setattr setsuid }
>>>>> chmod u+r  (0244 -> 0644) { setattr }
>>>>>
>>>>> If either the starting or the final attributes will have the setuid or
>>>>> setgid bits set you need this permission.
>>>> I'd like to understand better how this would be used.
>>>>
>>>> Suppose that I want to control the ability to create/modify privileged
>>>> executables on the system.  Given that SELinux already controls
>>>> capability usage, I can already do that by labeling privileged
>>>> executable with an appropriate type and controlling the ability to
>>>> create/modify/relabelto that type, without being concerned about the
>>>> suid bit.  Why do I need this check?  And if I need this check, then
>>>> don't I need a similar check on setting/clearing file capabilities on a
>>>> given file?
>>> One other tidbit: I don't believe that this check will get applied in
>>> the case where a suid/sgid binary is overwritten and the suid/sgid bits
>>> are forcibly cleared (ATTR_FORCE), as the selinux_inode_setattr() hook
>>> returns immediately in that case as it must not fail.
>>>
>>>> Last concern I have is with this check not being adequately granular
>>>> since it is a single check for setting or clearing the suid or sgid bit
>>>> of a file owned by any user, whereas it seems more security-relevant to
>>>> be setting the suid bit on a root-owned executable than to be clearing
>>>> it or to be setting the suid bit on a sds-owned executable.  I'm not
>>>> sure how to write a useful policy that lets users do things that are
>>>> harmless or of no interest while still enforcing a useful goal.
>>>>
>>>>> Signed-off-by: Eric Paris <eparis@redhat.com>
>>>>>
>>>>> ---
>>>>>
>>>>>  security/selinux/hooks.c                     |   22 ++++++++++++++++++++--
>>>>>  security/selinux/include/av_perm_to_string.h |    1 +
>>>>>  security/selinux/include/av_permissions.h    |    1 +
>>>>>  security/selinux/include/class_to_string.h   |    4 ++++
>>>>>  security/selinux/include/security.h          |    2 ++
>>>>>  security/selinux/selinuxfs.c                 |    3 ++-
>>>>>  security/selinux/ss/services.c               |    3 +++
>>>>>  7 files changed, 33 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>>>>> index 576e511..58af86a 100644
>>>>> --- a/security/selinux/hooks.c
>>>>> +++ b/security/selinux/hooks.c
>>>>> @@ -2659,6 +2659,8 @@ static int selinux_inode_permission(struct inode *inode, int mask)
>>>>>  static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>>>>>  {
>>>>>  	int rc;
>>>>> +	unsigned int mode = dentry->d_inode->i_mode;
>>>>> +	u32 av = 0;
>>>>>  
>>>>>  	rc = secondary_ops->inode_setattr(dentry, iattr);
>>>>>  	if (rc)
>>>>> @@ -2667,11 +2669,27 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>>>>>  	if (iattr->ia_valid & ATTR_FORCE)
>>>>>  		return 0;
>>>>>  
>>>>> +	/*
>>>>> +	 * are we changing mode?
>>>>> +	 * does policy support seperate suid/sgid checks?
>>>>> +	 * is this a regular file?
>>>>> +	 * do either the old inode->i_mode or the new iattr->i_mode have the
>>>>> +	 * suid/sgid bits set?
>>>>> +	 */
>>>>> +	if ((iattr->ia_valid & ATTR_MODE) &&
>>>>> +	    selinux_policycap_setsuidperm &&
>>>>> +	    (S_ISREG(mode)) &&
>>>>> +	    ((iattr->ia_mode & (S_ISUID | S_ISGID)) ||
>>>>> +	     (mode & (S_ISUID | S_ISGID))))
>>>>> +			av |= FILE__SETSUID;
>>>>> +
>>>>>  	if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
>>>>>  			       ATTR_ATIME_SET | ATTR_MTIME_SET))
>>>>> -		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
>>>>> +		av |= FILE__SETATTR;
>>>>> +	else
>>>>> +		av = FILE__WRITE;
>>>>>  
>>>>> -	return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
>>>>> +	return dentry_has_perm(current, NULL, dentry, av);
>>>>>  }
>>>>>  
>>>>>  static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
>>>>> diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
>>>>> index 1223b4f..c6c5c0e 100644
>>>>> --- a/security/selinux/include/av_perm_to_string.h
>>>>> +++ b/security/selinux/include/av_perm_to_string.h
>>>>> @@ -19,6 +19,7 @@
>>>>>     S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
>>>>>     S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
>>>>>     S_(SECCLASS_FILE, FILE__OPEN, "open")
>>>>> +   S_(SECCLASS_FILE, FILE__SETSUID, "setsuid")
>>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
>>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
>>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
>>>>> diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
>>>>> index c4c5116..cd6d566 100644
>>>>> --- a/security/selinux/include/av_permissions.h
>>>>> +++ b/security/selinux/include/av_permissions.h
>>>>> @@ -101,6 +101,7 @@
>>>>>  #define FILE__ENTRYPOINT                          0x00040000UL
>>>>>  #define FILE__EXECMOD                             0x00080000UL
>>>>>  #define FILE__OPEN                                0x00100000UL
>>>>> +#define FILE__SETSUID                             0x00200000UL
>>>>>  #define LNK_FILE__IOCTL                           0x00000001UL
>>>>>  #define LNK_FILE__READ                            0x00000002UL
>>>>>  #define LNK_FILE__WRITE                           0x00000004UL
>>>>> diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
>>>>> index bd813c3..0d11270 100644
>>>>> --- a/security/selinux/include/class_to_string.h
>>>>> +++ b/security/selinux/include/class_to_string.h
>>>>> @@ -72,3 +72,7 @@
>>>>>      S_(NULL)
>>>>>      S_("peer")
>>>>>      S_("capability2")
>>>>> +    S_(NULL)
>>>>> +    S_(NULL)
>>>>> +    S_(NULL)
>>>>> +    S_(NULL)
>>>>> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
>>>>> index 7244737..a604f05 100644
>>>>> --- a/security/selinux/include/security.h
>>>>> +++ b/security/selinux/include/security.h
>>>>> @@ -56,12 +56,14 @@ extern int selinux_mls_enabled;
>>>>>  enum {
>>>>>  	POLICYDB_CAPABILITY_NETPEER,
>>>>>  	POLICYDB_CAPABILITY_OPENPERM,
>>>>> +	POLICYDB_CAPABILITY_SETSUIDPERM,
>>>>>  	__POLICYDB_CAPABILITY_MAX
>>>>>  };
>>>>>  #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
>>>>>  
>>>>>  extern int selinux_policycap_netpeer;
>>>>>  extern int selinux_policycap_openperm;
>>>>> +extern int selinux_policycap_setsuidperm;
>>>>>  
>>>>>  /*
>>>>>   * type_datum properties
>>>>> diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
>>>>> index 69c9dcc..26ef62f 100644
>>>>> --- a/security/selinux/selinuxfs.c
>>>>> +++ b/security/selinux/selinuxfs.c
>>>>> @@ -42,7 +42,8 @@
>>>>>  /* Policy capability filenames */
>>>>>  static char *policycap_names[] = {
>>>>>  	"network_peer_controls",
>>>>> -	"open_perms"
>>>>> +	"open_perms",
>>>>> +	"setsuid_perms",
>>>>>  };
>>>>>  
>>>>>  unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
>>>>> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
>>>>> index 343c8ab..9ecd8e7 100644
>>>>> --- a/security/selinux/ss/services.c
>>>>> +++ b/security/selinux/ss/services.c
>>>>> @@ -64,6 +64,7 @@ unsigned int policydb_loaded_version;
>>>>>  
>>>>>  int selinux_policycap_netpeer;
>>>>>  int selinux_policycap_openperm;
>>>>> +int selinux_policycap_setsuidperm;
>>>>>  
>>>>>  /*
>>>>>   * This is declared in avc.c
>>>>> @@ -1615,6 +1616,8 @@ static void security_load_policycaps(void)
>>>>>  						  POLICYDB_CAPABILITY_NETPEER);
>>>>>  	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
>>>>>  						  POLICYDB_CAPABILITY_OPENPERM);
>>>>> +	selinux_policycap_setsuidperm = ebitmap_get_bit(&policydb.policycaps,
>>>>> +						  POLICYDB_CAPABILITY_SETSUIDPERM);
>>>>>  }
>>>>>  
>>>>>  extern void selinux_complete_init(void);
>>>>>
>> The reason I asked for this is for the confined administrator user.
>>
>> Say I am webadmin of a system.  I can run sudo to become
>> webadm_r:webadmin_t as UID 0.  I now want to change the permissions on a
>> cgi script to be executable.  If I can change it to setuid, or setgid, I
>> might be able to find an alternate root to executing the app with raised
>> privs.
>>
>> I just see this as a risk, and I see little reason why a confined
>> administrator would even need to setuid/setgid an application.
> 
> Well, as I noted when this came up as an RFC a year ago, the fact that
> they can create a setuid program doesn't mean that they can exercise any
> capabilities since we control that based on domain.  And rather than
> preventing them from setting the suid bit, it might be more useful to
> prevent them from executing a setuid program (regardless of who made it
> setuid) or letting it execute but not changing its uid in that case
> (just as we do under ptrace).
> 
> http://marc.info/?l=selinux&m=119013530120434&w=2
> 
Lets take another path to this.

nsplugin executes programs that want to setattr to
/home/dwalsh/.recently-used.xbel

Why I don't know.  But audit2allow tells me to add a rule

allow nsplugin_t user_home_t:file setattr;

Which I might just allow, since maybe changing the ownership on a file
is required.  (I am dont auditing it.)  If nsplugin_t was allowed
setattr, it could be used to chmod 4755 ~/myexe, and now another user on
the system would be able to run ~dwalsh/myexe as dwalsh.  (If they had
the same user type.)


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkj4+qEACgkQrlYvE4MpobOlMgCeKbBaLjhhYuPmEymIMCene1aH
SP0An3VaV+6UnL0fhl2pPcqVtfE3cdGT
=iAhK
-----END PGP SIGNATURE-----

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 20:09               ` Stephen Smalley
  2008-10-17 20:38                 ` Eric Paris
@ 2008-10-17 21:18                 ` Daniel J Walsh
  2008-10-20 12:27                   ` Stephen Smalley
  1 sibling, 1 reply; 23+ messages in thread
From: Daniel J Walsh @ 2008-10-17 21:18 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Eric Paris, selinux, jmorris, sgrubb

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Stephen Smalley wrote:
> On Fri, 2008-10-17 at 16:04 -0400, Eric Paris wrote:
>> On Fri, 2008-10-17 at 15:39 -0400, Stephen Smalley wrote:
>>
>>> I don't follow the above.  First, the CAP_SETUID capability controls the
>>> ability to use set*uid() system calls, not to execute setuid binaries
>>> (aside from a special case for shared state).  Second, if some other
>>> confined domain executes a setuid binary created by this user, it is
>>> still limited by the permissions granted to that original confined
>>> domain as far as SELinux is concerned.
>> He's saying there are almost 200 domains that can run setuid apps.
> 
> As I said, CAP_SETUID isn't about whether or not you can run a setuid
> app.  You can do that without CAP_SETUID.  Obviously since a normal
> unprivileged user shell can run a setuid program in the first place.
> 
>> Limiting the number of domains that can create new setuid apps limits
>> the number of places that these domains can go.  Clearly they are all
>> still confined to their domain and whatever it allows, but allowing them
>> to gain root priveledges may give them the ability to attack other parts
> 
> Wait - how did they gain root privileges?  root privileges are
> capabilities, and we control capabilities based on domain.
> 
>> of the system normally controlled by dac.  This certainly doesn't lessen
>> the MAC confinement.  Lets assume an audited system in which we are
>> certain the only suid app untrusted users are allowed to run is ping.
>> So the users have the right to run suid apps.  They are protected from
>> each other by DAC.
>>
>> Confined webadmin writes a program which is clears out other users
>> public_html when they get a spurious DMCA takedown notice.  He then
>> (because he is a lazy bumbling idiot) makes his script suid so he does
>> not have to go into his confined webadmin account constantly to delete
>> users webpages.
> 
> He could also make a daemon that runs under his uid and accepts commands
> via local socket.
> 
>> Normal DAC protects user2 from being attacked by user1.  Because of the
>> bumbling incompetance of confined webadmin user1 can now use this setuid
>> app to do things which he is allow by selinux policy but denied by
>> normal DAC permissions.
>>
>> Why did webadmin need to make a setuid app to begin with?  file caps are
>> already protected by CAP_SETFCAP.  Lets assume system policy says that
>> su should not be setuid.  Should the webadmin really be allowed to
>> easily override that system policy because he wants to use su - to get
>> to his confined domain instead of sudo?
> 
> He can't get to his confined domain via some other program unless policy
> says he can.  He can only get to some other uid that way.
> 
>>   She bumbling idiot really be
>> allowed to say add o+x to su - when the system policy only really wanted
>> group wheel to be able to run su?  Should the bumbling idiot be able to
>> remove the suid flag from a program and not be able to fix it?
>>
>> I think there are some real gains that can be made by limiting how
>> confined admins or untrusted users can deal with suid apps.
>>
>> I'd probably be inclined to add changing the uid/gid/other things that
>> clear setuid to be things which require this permission.  I don't see a
>> reason to allow my webadmin to chown su to himself...
> 
> He can't do that unless he owns su (or that itself is subject to
> fowner).  And chown'ing or writing to a suid app clears the suid bit
> forcibly. 
> 
> Come on, guys, you can do better.
> 
This hole discussion has actually opened me up to a new understanding.
SELinux right now does not prevent the execution of setuid applications
if you do not have setuid capability, it only prevents you from running
apps that actually execute the setuid() call.

I think this is a problem.  One of the things I have been saying in my
presentations is that running as staff_t will prevent you from running
any setuid application unless a transition is defined.  Turns out this
is wrong and I was lying.

# cp /usr/bin/id /usr/bin/myid
# chmod 4755 /usr/bin/myid

$ myid
uid=3267(dwalsh) gid=3267(dwalsh) euid=0(root) groups=3267(dwalsh)
context=staff_u:staff_r:staff_t:s0

So running a chmod o+s file as staff_t will run as EUID 0.  I think this
is something SELinux should block.  At least treat this the same way a
file system mounted nosetuid would.



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkj5AQkACgkQrlYvE4MpobPUJQCg5qRoFCBYh/bj1XU509v63F0H
UawAmwX5xiCLM85U8ZxupBzj5XEd68Jp
=paj/
-----END PGP SIGNATURE-----

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 20:50         ` Daniel J Walsh
@ 2008-10-20 12:26           ` Stephen Smalley
  2008-10-20 19:40             ` Daniel J Walsh
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2008-10-20 12:26 UTC (permalink / raw)
  To: Daniel J Walsh; +Cc: Eric Paris, selinux, jmorris, sgrubb

On Fri, 2008-10-17 at 16:50 -0400, Daniel J Walsh wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Stephen Smalley wrote:
> > On Fri, 2008-10-17 at 14:43 -0400, Daniel J Walsh wrote:
> >> -----BEGIN PGP SIGNED MESSAGE-----
> >> Hash: SHA1
> >>
> >> Stephen Smalley wrote:
> >>> On Fri, 2008-10-17 at 12:52 -0400, Stephen Smalley wrote:
> >>>> On Fri, 2008-10-17 at 11:40 -0400, Eric Paris wrote:
> >>>>> This patch adds a new permission, setsuid, to the file class.  This
> >>>>> permission is checked any time a file has its attributes modified
> >>>>> (setattr) and the setuid or setgid bits are involved.  The purpose for
> >>>>> this change is to further allow selinux to confine administrative
> >>>>> duties.  The example explains when the permission is needed and when it
> >>>>> is not:
> >>>>>
> >>>>> Start with a file with chmod 0644.
> >>>>> chmod u+s  (0644 -> 4644) { setattr setsuid }
> >>>>> chmod u-r  (4644 -> 4244) { setattr setsuid }
> >>>>> chmod u-s  (4244 -> 0244) { setattr setsuid }
> >>>>> chmod u+r  (0244 -> 0644) { setattr }
> >>>>>
> >>>>> If either the starting or the final attributes will have the setuid or
> >>>>> setgid bits set you need this permission.
> >>>> I'd like to understand better how this would be used.
> >>>>
> >>>> Suppose that I want to control the ability to create/modify privileged
> >>>> executables on the system.  Given that SELinux already controls
> >>>> capability usage, I can already do that by labeling privileged
> >>>> executable with an appropriate type and controlling the ability to
> >>>> create/modify/relabelto that type, without being concerned about the
> >>>> suid bit.  Why do I need this check?  And if I need this check, then
> >>>> don't I need a similar check on setting/clearing file capabilities on a
> >>>> given file?
> >>> One other tidbit: I don't believe that this check will get applied in
> >>> the case where a suid/sgid binary is overwritten and the suid/sgid bits
> >>> are forcibly cleared (ATTR_FORCE), as the selinux_inode_setattr() hook
> >>> returns immediately in that case as it must not fail.
> >>>
> >>>> Last concern I have is with this check not being adequately granular
> >>>> since it is a single check for setting or clearing the suid or sgid bit
> >>>> of a file owned by any user, whereas it seems more security-relevant to
> >>>> be setting the suid bit on a root-owned executable than to be clearing
> >>>> it or to be setting the suid bit on a sds-owned executable.  I'm not
> >>>> sure how to write a useful policy that lets users do things that are
> >>>> harmless or of no interest while still enforcing a useful goal.
> >>>>
> >>>>> Signed-off-by: Eric Paris <eparis@redhat.com>
> >>>>>
> >>>>> ---
> >>>>>
> >>>>>  security/selinux/hooks.c                     |   22 ++++++++++++++++++++--
> >>>>>  security/selinux/include/av_perm_to_string.h |    1 +
> >>>>>  security/selinux/include/av_permissions.h    |    1 +
> >>>>>  security/selinux/include/class_to_string.h   |    4 ++++
> >>>>>  security/selinux/include/security.h          |    2 ++
> >>>>>  security/selinux/selinuxfs.c                 |    3 ++-
> >>>>>  security/selinux/ss/services.c               |    3 +++
> >>>>>  7 files changed, 33 insertions(+), 3 deletions(-)
> >>>>>
> >>>>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> >>>>> index 576e511..58af86a 100644
> >>>>> --- a/security/selinux/hooks.c
> >>>>> +++ b/security/selinux/hooks.c
> >>>>> @@ -2659,6 +2659,8 @@ static int selinux_inode_permission(struct inode *inode, int mask)
> >>>>>  static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
> >>>>>  {
> >>>>>  	int rc;
> >>>>> +	unsigned int mode = dentry->d_inode->i_mode;
> >>>>> +	u32 av = 0;
> >>>>>  
> >>>>>  	rc = secondary_ops->inode_setattr(dentry, iattr);
> >>>>>  	if (rc)
> >>>>> @@ -2667,11 +2669,27 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
> >>>>>  	if (iattr->ia_valid & ATTR_FORCE)
> >>>>>  		return 0;
> >>>>>  
> >>>>> +	/*
> >>>>> +	 * are we changing mode?
> >>>>> +	 * does policy support seperate suid/sgid checks?
> >>>>> +	 * is this a regular file?
> >>>>> +	 * do either the old inode->i_mode or the new iattr->i_mode have the
> >>>>> +	 * suid/sgid bits set?
> >>>>> +	 */
> >>>>> +	if ((iattr->ia_valid & ATTR_MODE) &&
> >>>>> +	    selinux_policycap_setsuidperm &&
> >>>>> +	    (S_ISREG(mode)) &&
> >>>>> +	    ((iattr->ia_mode & (S_ISUID | S_ISGID)) ||
> >>>>> +	     (mode & (S_ISUID | S_ISGID))))
> >>>>> +			av |= FILE__SETSUID;
> >>>>> +
> >>>>>  	if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
> >>>>>  			       ATTR_ATIME_SET | ATTR_MTIME_SET))
> >>>>> -		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
> >>>>> +		av |= FILE__SETATTR;
> >>>>> +	else
> >>>>> +		av = FILE__WRITE;
> >>>>>  
> >>>>> -	return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
> >>>>> +	return dentry_has_perm(current, NULL, dentry, av);
> >>>>>  }
> >>>>>  
> >>>>>  static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
> >>>>> diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
> >>>>> index 1223b4f..c6c5c0e 100644
> >>>>> --- a/security/selinux/include/av_perm_to_string.h
> >>>>> +++ b/security/selinux/include/av_perm_to_string.h
> >>>>> @@ -19,6 +19,7 @@
> >>>>>     S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
> >>>>>     S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
> >>>>>     S_(SECCLASS_FILE, FILE__OPEN, "open")
> >>>>> +   S_(SECCLASS_FILE, FILE__SETSUID, "setsuid")
> >>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
> >>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
> >>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
> >>>>> diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
> >>>>> index c4c5116..cd6d566 100644
> >>>>> --- a/security/selinux/include/av_permissions.h
> >>>>> +++ b/security/selinux/include/av_permissions.h
> >>>>> @@ -101,6 +101,7 @@
> >>>>>  #define FILE__ENTRYPOINT                          0x00040000UL
> >>>>>  #define FILE__EXECMOD                             0x00080000UL
> >>>>>  #define FILE__OPEN                                0x00100000UL
> >>>>> +#define FILE__SETSUID                             0x00200000UL
> >>>>>  #define LNK_FILE__IOCTL                           0x00000001UL
> >>>>>  #define LNK_FILE__READ                            0x00000002UL
> >>>>>  #define LNK_FILE__WRITE                           0x00000004UL
> >>>>> diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
> >>>>> index bd813c3..0d11270 100644
> >>>>> --- a/security/selinux/include/class_to_string.h
> >>>>> +++ b/security/selinux/include/class_to_string.h
> >>>>> @@ -72,3 +72,7 @@
> >>>>>      S_(NULL)
> >>>>>      S_("peer")
> >>>>>      S_("capability2")
> >>>>> +    S_(NULL)
> >>>>> +    S_(NULL)
> >>>>> +    S_(NULL)
> >>>>> +    S_(NULL)
> >>>>> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
> >>>>> index 7244737..a604f05 100644
> >>>>> --- a/security/selinux/include/security.h
> >>>>> +++ b/security/selinux/include/security.h
> >>>>> @@ -56,12 +56,14 @@ extern int selinux_mls_enabled;
> >>>>>  enum {
> >>>>>  	POLICYDB_CAPABILITY_NETPEER,
> >>>>>  	POLICYDB_CAPABILITY_OPENPERM,
> >>>>> +	POLICYDB_CAPABILITY_SETSUIDPERM,
> >>>>>  	__POLICYDB_CAPABILITY_MAX
> >>>>>  };
> >>>>>  #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
> >>>>>  
> >>>>>  extern int selinux_policycap_netpeer;
> >>>>>  extern int selinux_policycap_openperm;
> >>>>> +extern int selinux_policycap_setsuidperm;
> >>>>>  
> >>>>>  /*
> >>>>>   * type_datum properties
> >>>>> diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
> >>>>> index 69c9dcc..26ef62f 100644
> >>>>> --- a/security/selinux/selinuxfs.c
> >>>>> +++ b/security/selinux/selinuxfs.c
> >>>>> @@ -42,7 +42,8 @@
> >>>>>  /* Policy capability filenames */
> >>>>>  static char *policycap_names[] = {
> >>>>>  	"network_peer_controls",
> >>>>> -	"open_perms"
> >>>>> +	"open_perms",
> >>>>> +	"setsuid_perms",
> >>>>>  };
> >>>>>  
> >>>>>  unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
> >>>>> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> >>>>> index 343c8ab..9ecd8e7 100644
> >>>>> --- a/security/selinux/ss/services.c
> >>>>> +++ b/security/selinux/ss/services.c
> >>>>> @@ -64,6 +64,7 @@ unsigned int policydb_loaded_version;
> >>>>>  
> >>>>>  int selinux_policycap_netpeer;
> >>>>>  int selinux_policycap_openperm;
> >>>>> +int selinux_policycap_setsuidperm;
> >>>>>  
> >>>>>  /*
> >>>>>   * This is declared in avc.c
> >>>>> @@ -1615,6 +1616,8 @@ static void security_load_policycaps(void)
> >>>>>  						  POLICYDB_CAPABILITY_NETPEER);
> >>>>>  	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
> >>>>>  						  POLICYDB_CAPABILITY_OPENPERM);
> >>>>> +	selinux_policycap_setsuidperm = ebitmap_get_bit(&policydb.policycaps,
> >>>>> +						  POLICYDB_CAPABILITY_SETSUIDPERM);
> >>>>>  }
> >>>>>  
> >>>>>  extern void selinux_complete_init(void);
> >>>>>
> >> The reason I asked for this is for the confined administrator user.
> >>
> >> Say I am webadmin of a system.  I can run sudo to become
> >> webadm_r:webadmin_t as UID 0.  I now want to change the permissions on a
> >> cgi script to be executable.  If I can change it to setuid, or setgid, I
> >> might be able to find an alternate root to executing the app with raised
> >> privs.
> >>
> >> I just see this as a risk, and I see little reason why a confined
> >> administrator would even need to setuid/setgid an application.
> > 
> > Well, as I noted when this came up as an RFC a year ago, the fact that
> > they can create a setuid program doesn't mean that they can exercise any
> > capabilities since we control that based on domain.  And rather than
> > preventing them from setting the suid bit, it might be more useful to
> > prevent them from executing a setuid program (regardless of who made it
> > setuid) or letting it execute but not changing its uid in that case
> > (just as we do under ptrace).
> > 
> > http://marc.info/?l=selinux&m=119013530120434&w=2
> > 
> Lets take another path to this.
> 
> nsplugin executes programs that want to setattr to
> /home/dwalsh/.recently-used.xbel
> 
> Why I don't know.  But audit2allow tells me to add a rule
> 
> allow nsplugin_t user_home_t:file setattr;
> 
> Which I might just allow, since maybe changing the ownership on a file
> is required.  (I am dont auditing it.)  If nsplugin_t was allowed
> setattr, it could be used to chmod 4755 ~/myexe, and now another user on
> the system would be able to run ~dwalsh/myexe as dwalsh.  (If they had
> the same user type.)

Ok, so what you want to do is control the ability to create additional
"entrypoints" into a user identity.  In which case you want to control
the following actions:
- making an executable suid (chmod with suid bit set),
- adding further execute access to an existing suid executable (chmod +x
of a suid executable _or_ modifying the ACL of a suid executable).

But I don't see the benefit to you of controlling the ability to clear
the suid bit or modifying the rw mode bits on a suid executable (writing
to a suid executable forcibly clears the suid bit, so you end up with a
program that is no longer suid at all).  Using the same permission for
all of the actions covered in Eric's patch just increases the likelihood
that you'll have to grant it in some cases where you don't want to allow
the particular two actions above.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 21:18                 ` Daniel J Walsh
@ 2008-10-20 12:27                   ` Stephen Smalley
  2008-10-20 19:25                     ` Daniel J Walsh
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2008-10-20 12:27 UTC (permalink / raw)
  To: Daniel J Walsh; +Cc: Eric Paris, selinux, jmorris, sgrubb

On Fri, 2008-10-17 at 17:18 -0400, Daniel J Walsh wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Stephen Smalley wrote:
> > On Fri, 2008-10-17 at 16:04 -0400, Eric Paris wrote:
> >> On Fri, 2008-10-17 at 15:39 -0400, Stephen Smalley wrote:
> >>
> >>> I don't follow the above.  First, the CAP_SETUID capability controls the
> >>> ability to use set*uid() system calls, not to execute setuid binaries
> >>> (aside from a special case for shared state).  Second, if some other
> >>> confined domain executes a setuid binary created by this user, it is
> >>> still limited by the permissions granted to that original confined
> >>> domain as far as SELinux is concerned.
> >> He's saying there are almost 200 domains that can run setuid apps.
> > 
> > As I said, CAP_SETUID isn't about whether or not you can run a setuid
> > app.  You can do that without CAP_SETUID.  Obviously since a normal
> > unprivileged user shell can run a setuid program in the first place.
> > 
> >> Limiting the number of domains that can create new setuid apps limits
> >> the number of places that these domains can go.  Clearly they are all
> >> still confined to their domain and whatever it allows, but allowing them
> >> to gain root priveledges may give them the ability to attack other parts
> > 
> > Wait - how did they gain root privileges?  root privileges are
> > capabilities, and we control capabilities based on domain.
> > 
> >> of the system normally controlled by dac.  This certainly doesn't lessen
> >> the MAC confinement.  Lets assume an audited system in which we are
> >> certain the only suid app untrusted users are allowed to run is ping.
> >> So the users have the right to run suid apps.  They are protected from
> >> each other by DAC.
> >>
> >> Confined webadmin writes a program which is clears out other users
> >> public_html when they get a spurious DMCA takedown notice.  He then
> >> (because he is a lazy bumbling idiot) makes his script suid so he does
> >> not have to go into his confined webadmin account constantly to delete
> >> users webpages.
> > 
> > He could also make a daemon that runs under his uid and accepts commands
> > via local socket.
> > 
> >> Normal DAC protects user2 from being attacked by user1.  Because of the
> >> bumbling incompetance of confined webadmin user1 can now use this setuid
> >> app to do things which he is allow by selinux policy but denied by
> >> normal DAC permissions.
> >>
> >> Why did webadmin need to make a setuid app to begin with?  file caps are
> >> already protected by CAP_SETFCAP.  Lets assume system policy says that
> >> su should not be setuid.  Should the webadmin really be allowed to
> >> easily override that system policy because he wants to use su - to get
> >> to his confined domain instead of sudo?
> > 
> > He can't get to his confined domain via some other program unless policy
> > says he can.  He can only get to some other uid that way.
> > 
> >>   She bumbling idiot really be
> >> allowed to say add o+x to su - when the system policy only really wanted
> >> group wheel to be able to run su?  Should the bumbling idiot be able to
> >> remove the suid flag from a program and not be able to fix it?
> >>
> >> I think there are some real gains that can be made by limiting how
> >> confined admins or untrusted users can deal with suid apps.
> >>
> >> I'd probably be inclined to add changing the uid/gid/other things that
> >> clear setuid to be things which require this permission.  I don't see a
> >> reason to allow my webadmin to chown su to himself...
> > 
> > He can't do that unless he owns su (or that itself is subject to
> > fowner).  And chown'ing or writing to a suid app clears the suid bit
> > forcibly. 
> > 
> > Come on, guys, you can do better.
> > 
> This hole discussion has actually opened me up to a new understanding.
> SELinux right now does not prevent the execution of setuid applications
> if you do not have setuid capability, it only prevents you from running
> apps that actually execute the setuid() call.
> 
> I think this is a problem.  One of the things I have been saying in my
> presentations is that running as staff_t will prevent you from running
> any setuid application unless a transition is defined.  Turns out this
> is wrong and I was lying.
> 
> # cp /usr/bin/id /usr/bin/myid
> # chmod 4755 /usr/bin/myid
> 
> $ myid
> uid=3267(dwalsh) gid=3267(dwalsh) euid=0(root) groups=3267(dwalsh)
> context=staff_u:staff_r:staff_t:s0
> 
> So running a chmod o+s file as staff_t will run as EUID 0.  I think this
> is something SELinux should block.  At least treat this the same way a
> file system mounted nosetuid would.

That would require a control on the exec path instead of chmod/setattr -
which is what I suggested a year ago in response to the original RFC.

But note that gaining EUID 0 does not automatically grant privilege
under SELinux - your capabilities are still limited based on domain and
your ability to read/write even root-owned files is controlled based on
the (domain, type, file class) triple.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-17 20:38                 ` Eric Paris
  2008-10-17 20:49                   ` Eric Paris
@ 2008-10-20 12:30                   ` Stephen Smalley
  1 sibling, 0 replies; 23+ messages in thread
From: Stephen Smalley @ 2008-10-20 12:30 UTC (permalink / raw)
  To: Eric Paris; +Cc: Daniel J Walsh, selinux, jmorris, sgrubb

On Fri, 2008-10-17 at 16:38 -0400, Eric Paris wrote:
> Anyway, I'm not arguing this is going to provide greater MAC confinement
> and I'm not able to describe security goals in terms of MAC domains.
> I'm merely stating that a SELinux confined admin is easily able change
> DAC security policy as defined by an organization.

DAC by definition is subject to control by the user, not by the
organization.  

>   Yes, DAC sercurity
> policy that I'm talking about is mathmatically provable and that's the
> part that I'm sure you initially reject, but it doesn't make it
> pointless or even detractive.

It isn't about being provable but rather providing any actual security
benefit.

However, I'm open to the notion of controlling making additional
entrypoints to a user identity, as described in my response to Dan, but
I don't believe that this patch is the way to achieve that.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-20 12:27                   ` Stephen Smalley
@ 2008-10-20 19:25                     ` Daniel J Walsh
  2008-10-20 20:04                       ` Stephen Smalley
  0 siblings, 1 reply; 23+ messages in thread
From: Daniel J Walsh @ 2008-10-20 19:25 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Eric Paris, selinux, jmorris, sgrubb

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Stephen Smalley wrote:
> On Fri, 2008-10-17 at 17:18 -0400, Daniel J Walsh wrote:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>> Stephen Smalley wrote:
>>> On Fri, 2008-10-17 at 16:04 -0400, Eric Paris wrote:
>>>> On Fri, 2008-10-17 at 15:39 -0400, Stephen Smalley wrote:
>>>>
>>>>> I don't follow the above.  First, the CAP_SETUID capability controls the
>>>>> ability to use set*uid() system calls, not to execute setuid binaries
>>>>> (aside from a special case for shared state).  Second, if some other
>>>>> confined domain executes a setuid binary created by this user, it is
>>>>> still limited by the permissions granted to that original confined
>>>>> domain as far as SELinux is concerned.
>>>> He's saying there are almost 200 domains that can run setuid apps.
>>> As I said, CAP_SETUID isn't about whether or not you can run a setuid
>>> app.  You can do that without CAP_SETUID.  Obviously since a normal
>>> unprivileged user shell can run a setuid program in the first place.
>>>
>>>> Limiting the number of domains that can create new setuid apps limits
>>>> the number of places that these domains can go.  Clearly they are all
>>>> still confined to their domain and whatever it allows, but allowing them
>>>> to gain root priveledges may give them the ability to attack other parts
>>> Wait - how did they gain root privileges?  root privileges are
>>> capabilities, and we control capabilities based on domain.
>>>
>>>> of the system normally controlled by dac.  This certainly doesn't lessen
>>>> the MAC confinement.  Lets assume an audited system in which we are
>>>> certain the only suid app untrusted users are allowed to run is ping.
>>>> So the users have the right to run suid apps.  They are protected from
>>>> each other by DAC.
>>>>
>>>> Confined webadmin writes a program which is clears out other users
>>>> public_html when they get a spurious DMCA takedown notice.  He then
>>>> (because he is a lazy bumbling idiot) makes his script suid so he does
>>>> not have to go into his confined webadmin account constantly to delete
>>>> users webpages.
>>> He could also make a daemon that runs under his uid and accepts commands
>>> via local socket.
>>>
>>>> Normal DAC protects user2 from being attacked by user1.  Because of the
>>>> bumbling incompetance of confined webadmin user1 can now use this setuid
>>>> app to do things which he is allow by selinux policy but denied by
>>>> normal DAC permissions.
>>>>
>>>> Why did webadmin need to make a setuid app to begin with?  file caps are
>>>> already protected by CAP_SETFCAP.  Lets assume system policy says that
>>>> su should not be setuid.  Should the webadmin really be allowed to
>>>> easily override that system policy because he wants to use su - to get
>>>> to his confined domain instead of sudo?
>>> He can't get to his confined domain via some other program unless policy
>>> says he can.  He can only get to some other uid that way.
>>>
>>>>   She bumbling idiot really be
>>>> allowed to say add o+x to su - when the system policy only really wanted
>>>> group wheel to be able to run su?  Should the bumbling idiot be able to
>>>> remove the suid flag from a program and not be able to fix it?
>>>>
>>>> I think there are some real gains that can be made by limiting how
>>>> confined admins or untrusted users can deal with suid apps.
>>>>
>>>> I'd probably be inclined to add changing the uid/gid/other things that
>>>> clear setuid to be things which require this permission.  I don't see a
>>>> reason to allow my webadmin to chown su to himself...
>>> He can't do that unless he owns su (or that itself is subject to
>>> fowner).  And chown'ing or writing to a suid app clears the suid bit
>>> forcibly. 
>>>
>>> Come on, guys, you can do better.
>>>
>> This hole discussion has actually opened me up to a new understanding.
>> SELinux right now does not prevent the execution of setuid applications
>> if you do not have setuid capability, it only prevents you from running
>> apps that actually execute the setuid() call.
>>
>> I think this is a problem.  One of the things I have been saying in my
>> presentations is that running as staff_t will prevent you from running
>> any setuid application unless a transition is defined.  Turns out this
>> is wrong and I was lying.
>>
>> # cp /usr/bin/id /usr/bin/myid
>> # chmod 4755 /usr/bin/myid
>>
>> $ myid
>> uid=3267(dwalsh) gid=3267(dwalsh) euid=0(root) groups=3267(dwalsh)
>> context=staff_u:staff_r:staff_t:s0
>>
>> So running a chmod o+s file as staff_t will run as EUID 0.  I think this
>> is something SELinux should block.  At least treat this the same way a
>> file system mounted nosetuid would.
> 
> That would require a control on the exec path instead of chmod/setattr -
> which is what I suggested a year ago in response to the original RFC.
> 
Sounds like a good idea, I guess you should have pushed it.  :^)

> But note that gaining EUID 0 does not automatically grant privilege
> under SELinux - your capabilities are still limited based on domain and
> your ability to read/write even root-owned files is controlled based on
> the (domain, type, file class) triple.
> 

Understood.  But we still have the risc of having a fairly wide open
user type like staff_t tripping on a setuid app that could exculate
privs.  Or the ability for two staff_t users to attach each other
through setuid apps.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkj820UACgkQrlYvE4MpobMpBgCg6bgdShjBt9SNMibqrUos+Wqt
UHsAnjKornOi6HKExM5ktKNZbPRSz1tC
=rsXR
-----END PGP SIGNATURE-----

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-20 12:26           ` Stephen Smalley
@ 2008-10-20 19:40             ` Daniel J Walsh
  2008-10-20 22:52               ` James Morris
  0 siblings, 1 reply; 23+ messages in thread
From: Daniel J Walsh @ 2008-10-20 19:40 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Eric Paris, selinux, jmorris, sgrubb

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Stephen Smalley wrote:
> On Fri, 2008-10-17 at 16:50 -0400, Daniel J Walsh wrote:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>> Stephen Smalley wrote:
>>> On Fri, 2008-10-17 at 14:43 -0400, Daniel J Walsh wrote:
>>>> -----BEGIN PGP SIGNED MESSAGE-----
>>>> Hash: SHA1
>>>>
>>>> Stephen Smalley wrote:
>>>>> On Fri, 2008-10-17 at 12:52 -0400, Stephen Smalley wrote:
>>>>>> On Fri, 2008-10-17 at 11:40 -0400, Eric Paris wrote:
>>>>>>> This patch adds a new permission, setsuid, to the file class.  This
>>>>>>> permission is checked any time a file has its attributes modified
>>>>>>> (setattr) and the setuid or setgid bits are involved.  The purpose for
>>>>>>> this change is to further allow selinux to confine administrative
>>>>>>> duties.  The example explains when the permission is needed and when it
>>>>>>> is not:
>>>>>>>
>>>>>>> Start with a file with chmod 0644.
>>>>>>> chmod u+s  (0644 -> 4644) { setattr setsuid }
>>>>>>> chmod u-r  (4644 -> 4244) { setattr setsuid }
>>>>>>> chmod u-s  (4244 -> 0244) { setattr setsuid }
>>>>>>> chmod u+r  (0244 -> 0644) { setattr }
>>>>>>>
>>>>>>> If either the starting or the final attributes will have the setuid or
>>>>>>> setgid bits set you need this permission.
>>>>>> I'd like to understand better how this would be used.
>>>>>>
>>>>>> Suppose that I want to control the ability to create/modify privileged
>>>>>> executables on the system.  Given that SELinux already controls
>>>>>> capability usage, I can already do that by labeling privileged
>>>>>> executable with an appropriate type and controlling the ability to
>>>>>> create/modify/relabelto that type, without being concerned about the
>>>>>> suid bit.  Why do I need this check?  And if I need this check, then
>>>>>> don't I need a similar check on setting/clearing file capabilities on a
>>>>>> given file?
>>>>> One other tidbit: I don't believe that this check will get applied in
>>>>> the case where a suid/sgid binary is overwritten and the suid/sgid bits
>>>>> are forcibly cleared (ATTR_FORCE), as the selinux_inode_setattr() hook
>>>>> returns immediately in that case as it must not fail.
>>>>>
>>>>>> Last concern I have is with this check not being adequately granular
>>>>>> since it is a single check for setting or clearing the suid or sgid bit
>>>>>> of a file owned by any user, whereas it seems more security-relevant to
>>>>>> be setting the suid bit on a root-owned executable than to be clearing
>>>>>> it or to be setting the suid bit on a sds-owned executable.  I'm not
>>>>>> sure how to write a useful policy that lets users do things that are
>>>>>> harmless or of no interest while still enforcing a useful goal.
>>>>>>
>>>>>>> Signed-off-by: Eric Paris <eparis@redhat.com>
>>>>>>>
>>>>>>> ---
>>>>>>>
>>>>>>>  security/selinux/hooks.c                     |   22 ++++++++++++++++++++--
>>>>>>>  security/selinux/include/av_perm_to_string.h |    1 +
>>>>>>>  security/selinux/include/av_permissions.h    |    1 +
>>>>>>>  security/selinux/include/class_to_string.h   |    4 ++++
>>>>>>>  security/selinux/include/security.h          |    2 ++
>>>>>>>  security/selinux/selinuxfs.c                 |    3 ++-
>>>>>>>  security/selinux/ss/services.c               |    3 +++
>>>>>>>  7 files changed, 33 insertions(+), 3 deletions(-)
>>>>>>>
>>>>>>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>>>>>>> index 576e511..58af86a 100644
>>>>>>> --- a/security/selinux/hooks.c
>>>>>>> +++ b/security/selinux/hooks.c
>>>>>>> @@ -2659,6 +2659,8 @@ static int selinux_inode_permission(struct inode *inode, int mask)
>>>>>>>  static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>>>>>>>  {
>>>>>>>  	int rc;
>>>>>>> +	unsigned int mode = dentry->d_inode->i_mode;
>>>>>>> +	u32 av = 0;
>>>>>>>  
>>>>>>>  	rc = secondary_ops->inode_setattr(dentry, iattr);
>>>>>>>  	if (rc)
>>>>>>> @@ -2667,11 +2669,27 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>>>>>>>  	if (iattr->ia_valid & ATTR_FORCE)
>>>>>>>  		return 0;
>>>>>>>  
>>>>>>> +	/*
>>>>>>> +	 * are we changing mode?
>>>>>>> +	 * does policy support seperate suid/sgid checks?
>>>>>>> +	 * is this a regular file?
>>>>>>> +	 * do either the old inode->i_mode or the new iattr->i_mode have the
>>>>>>> +	 * suid/sgid bits set?
>>>>>>> +	 */
>>>>>>> +	if ((iattr->ia_valid & ATTR_MODE) &&
>>>>>>> +	    selinux_policycap_setsuidperm &&
>>>>>>> +	    (S_ISREG(mode)) &&
>>>>>>> +	    ((iattr->ia_mode & (S_ISUID | S_ISGID)) ||
>>>>>>> +	     (mode & (S_ISUID | S_ISGID))))
>>>>>>> +			av |= FILE__SETSUID;
>>>>>>> +
>>>>>>>  	if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
>>>>>>>  			       ATTR_ATIME_SET | ATTR_MTIME_SET))
>>>>>>> -		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
>>>>>>> +		av |= FILE__SETATTR;
>>>>>>> +	else
>>>>>>> +		av = FILE__WRITE;
>>>>>>>  
>>>>>>> -	return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
>>>>>>> +	return dentry_has_perm(current, NULL, dentry, av);
>>>>>>>  }
>>>>>>>  
>>>>>>>  static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
>>>>>>> diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
>>>>>>> index 1223b4f..c6c5c0e 100644
>>>>>>> --- a/security/selinux/include/av_perm_to_string.h
>>>>>>> +++ b/security/selinux/include/av_perm_to_string.h
>>>>>>> @@ -19,6 +19,7 @@
>>>>>>>     S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
>>>>>>>     S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
>>>>>>>     S_(SECCLASS_FILE, FILE__OPEN, "open")
>>>>>>> +   S_(SECCLASS_FILE, FILE__SETSUID, "setsuid")
>>>>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
>>>>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
>>>>>>>     S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
>>>>>>> diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
>>>>>>> index c4c5116..cd6d566 100644
>>>>>>> --- a/security/selinux/include/av_permissions.h
>>>>>>> +++ b/security/selinux/include/av_permissions.h
>>>>>>> @@ -101,6 +101,7 @@
>>>>>>>  #define FILE__ENTRYPOINT                          0x00040000UL
>>>>>>>  #define FILE__EXECMOD                             0x00080000UL
>>>>>>>  #define FILE__OPEN                                0x00100000UL
>>>>>>> +#define FILE__SETSUID                             0x00200000UL
>>>>>>>  #define LNK_FILE__IOCTL                           0x00000001UL
>>>>>>>  #define LNK_FILE__READ                            0x00000002UL
>>>>>>>  #define LNK_FILE__WRITE                           0x00000004UL
>>>>>>> diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
>>>>>>> index bd813c3..0d11270 100644
>>>>>>> --- a/security/selinux/include/class_to_string.h
>>>>>>> +++ b/security/selinux/include/class_to_string.h
>>>>>>> @@ -72,3 +72,7 @@
>>>>>>>      S_(NULL)
>>>>>>>      S_("peer")
>>>>>>>      S_("capability2")
>>>>>>> +    S_(NULL)
>>>>>>> +    S_(NULL)
>>>>>>> +    S_(NULL)
>>>>>>> +    S_(NULL)
>>>>>>> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
>>>>>>> index 7244737..a604f05 100644
>>>>>>> --- a/security/selinux/include/security.h
>>>>>>> +++ b/security/selinux/include/security.h
>>>>>>> @@ -56,12 +56,14 @@ extern int selinux_mls_enabled;
>>>>>>>  enum {
>>>>>>>  	POLICYDB_CAPABILITY_NETPEER,
>>>>>>>  	POLICYDB_CAPABILITY_OPENPERM,
>>>>>>> +	POLICYDB_CAPABILITY_SETSUIDPERM,
>>>>>>>  	__POLICYDB_CAPABILITY_MAX
>>>>>>>  };
>>>>>>>  #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
>>>>>>>  
>>>>>>>  extern int selinux_policycap_netpeer;
>>>>>>>  extern int selinux_policycap_openperm;
>>>>>>> +extern int selinux_policycap_setsuidperm;
>>>>>>>  
>>>>>>>  /*
>>>>>>>   * type_datum properties
>>>>>>> diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
>>>>>>> index 69c9dcc..26ef62f 100644
>>>>>>> --- a/security/selinux/selinuxfs.c
>>>>>>> +++ b/security/selinux/selinuxfs.c
>>>>>>> @@ -42,7 +42,8 @@
>>>>>>>  /* Policy capability filenames */
>>>>>>>  static char *policycap_names[] = {
>>>>>>>  	"network_peer_controls",
>>>>>>> -	"open_perms"
>>>>>>> +	"open_perms",
>>>>>>> +	"setsuid_perms",
>>>>>>>  };
>>>>>>>  
>>>>>>>  unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
>>>>>>> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
>>>>>>> index 343c8ab..9ecd8e7 100644
>>>>>>> --- a/security/selinux/ss/services.c
>>>>>>> +++ b/security/selinux/ss/services.c
>>>>>>> @@ -64,6 +64,7 @@ unsigned int policydb_loaded_version;
>>>>>>>  
>>>>>>>  int selinux_policycap_netpeer;
>>>>>>>  int selinux_policycap_openperm;
>>>>>>> +int selinux_policycap_setsuidperm;
>>>>>>>  
>>>>>>>  /*
>>>>>>>   * This is declared in avc.c
>>>>>>> @@ -1615,6 +1616,8 @@ static void security_load_policycaps(void)
>>>>>>>  						  POLICYDB_CAPABILITY_NETPEER);
>>>>>>>  	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
>>>>>>>  						  POLICYDB_CAPABILITY_OPENPERM);
>>>>>>> +	selinux_policycap_setsuidperm = ebitmap_get_bit(&policydb.policycaps,
>>>>>>> +						  POLICYDB_CAPABILITY_SETSUIDPERM);
>>>>>>>  }
>>>>>>>  
>>>>>>>  extern void selinux_complete_init(void);
>>>>>>>
>>>> The reason I asked for this is for the confined administrator user.
>>>>
>>>> Say I am webadmin of a system.  I can run sudo to become
>>>> webadm_r:webadmin_t as UID 0.  I now want to change the permissions on a
>>>> cgi script to be executable.  If I can change it to setuid, or setgid, I
>>>> might be able to find an alternate root to executing the app with raised
>>>> privs.
>>>>
>>>> I just see this as a risk, and I see little reason why a confined
>>>> administrator would even need to setuid/setgid an application.
>>> Well, as I noted when this came up as an RFC a year ago, the fact that
>>> they can create a setuid program doesn't mean that they can exercise any
>>> capabilities since we control that based on domain.  And rather than
>>> preventing them from setting the suid bit, it might be more useful to
>>> prevent them from executing a setuid program (regardless of who made it
>>> setuid) or letting it execute but not changing its uid in that case
>>> (just as we do under ptrace).
>>>
>>> http://marc.info/?l=selinux&m=119013530120434&w=2
>>>
>> Lets take another path to this.
>>
>> nsplugin executes programs that want to setattr to
>> /home/dwalsh/.recently-used.xbel
>>
>> Why I don't know.  But audit2allow tells me to add a rule
>>
>> allow nsplugin_t user_home_t:file setattr;
>>
>> Which I might just allow, since maybe changing the ownership on a file
>> is required.  (I am dont auditing it.)  If nsplugin_t was allowed
>> setattr, it could be used to chmod 4755 ~/myexe, and now another user on
>> the system would be able to run ~dwalsh/myexe as dwalsh.  (If they had
>> the same user type.)
> 
> Ok, so what you want to do is control the ability to create additional
> "entrypoints" into a user identity.  In which case you want to control
> the following actions:
> - making an executable suid (chmod with suid bit set),
> - adding further execute access to an existing suid executable (chmod +x
> of a suid executable _or_ modifying the ACL of a suid executable).
> 
> But I don't see the benefit to you of controlling the ability to clear
> the suid bit or modifying the rw mode bits on a suid executable (writing
> to a suid executable forcibly clears the suid bit, so you end up with a
> program that is no longer suid at all).  Using the same permission for
> all of the actions covered in Eric's patch just increases the likelihood
> that you'll have to grant it in some cases where you don't want to allow
> the particular two actions above.
> 
Fine, I don't care about this either.  So setting the setuid bit on
would be the only thing we watch.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkj83pUACgkQrlYvE4MpobNCngCfbIO9itGMvOEu/00rTZMEuPif
98sAniARbXki0BBJgTPRijUA3c46HamM
=4Cwo
-----END PGP SIGNATURE-----

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-20 19:25                     ` Daniel J Walsh
@ 2008-10-20 20:04                       ` Stephen Smalley
  2008-10-20 20:12                         ` Eric Paris
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2008-10-20 20:04 UTC (permalink / raw)
  To: Daniel J Walsh; +Cc: Eric Paris, selinux, jmorris, sgrubb

On Mon, 2008-10-20 at 15:25 -0400, Daniel J Walsh wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Stephen Smalley wrote:
> > On Fri, 2008-10-17 at 17:18 -0400, Daniel J Walsh wrote:
> >> -----BEGIN PGP SIGNED MESSAGE-----
> >> Hash: SHA1
> >>
> >> Stephen Smalley wrote:
> >>> On Fri, 2008-10-17 at 16:04 -0400, Eric Paris wrote:
> >>>> On Fri, 2008-10-17 at 15:39 -0400, Stephen Smalley wrote:
> >>>>
> >>>>> I don't follow the above.  First, the CAP_SETUID capability controls the
> >>>>> ability to use set*uid() system calls, not to execute setuid binaries
> >>>>> (aside from a special case for shared state).  Second, if some other
> >>>>> confined domain executes a setuid binary created by this user, it is
> >>>>> still limited by the permissions granted to that original confined
> >>>>> domain as far as SELinux is concerned.
> >>>> He's saying there are almost 200 domains that can run setuid apps.
> >>> As I said, CAP_SETUID isn't about whether or not you can run a setuid
> >>> app.  You can do that without CAP_SETUID.  Obviously since a normal
> >>> unprivileged user shell can run a setuid program in the first place.
> >>>
> >>>> Limiting the number of domains that can create new setuid apps limits
> >>>> the number of places that these domains can go.  Clearly they are all
> >>>> still confined to their domain and whatever it allows, but allowing them
> >>>> to gain root priveledges may give them the ability to attack other parts
> >>> Wait - how did they gain root privileges?  root privileges are
> >>> capabilities, and we control capabilities based on domain.
> >>>
> >>>> of the system normally controlled by dac.  This certainly doesn't lessen
> >>>> the MAC confinement.  Lets assume an audited system in which we are
> >>>> certain the only suid app untrusted users are allowed to run is ping.
> >>>> So the users have the right to run suid apps.  They are protected from
> >>>> each other by DAC.
> >>>>
> >>>> Confined webadmin writes a program which is clears out other users
> >>>> public_html when they get a spurious DMCA takedown notice.  He then
> >>>> (because he is a lazy bumbling idiot) makes his script suid so he does
> >>>> not have to go into his confined webadmin account constantly to delete
> >>>> users webpages.
> >>> He could also make a daemon that runs under his uid and accepts commands
> >>> via local socket.
> >>>
> >>>> Normal DAC protects user2 from being attacked by user1.  Because of the
> >>>> bumbling incompetance of confined webadmin user1 can now use this setuid
> >>>> app to do things which he is allow by selinux policy but denied by
> >>>> normal DAC permissions.
> >>>>
> >>>> Why did webadmin need to make a setuid app to begin with?  file caps are
> >>>> already protected by CAP_SETFCAP.  Lets assume system policy says that
> >>>> su should not be setuid.  Should the webadmin really be allowed to
> >>>> easily override that system policy because he wants to use su - to get
> >>>> to his confined domain instead of sudo?
> >>> He can't get to his confined domain via some other program unless policy
> >>> says he can.  He can only get to some other uid that way.
> >>>
> >>>>   She bumbling idiot really be
> >>>> allowed to say add o+x to su - when the system policy only really wanted
> >>>> group wheel to be able to run su?  Should the bumbling idiot be able to
> >>>> remove the suid flag from a program and not be able to fix it?
> >>>>
> >>>> I think there are some real gains that can be made by limiting how
> >>>> confined admins or untrusted users can deal with suid apps.
> >>>>
> >>>> I'd probably be inclined to add changing the uid/gid/other things that
> >>>> clear setuid to be things which require this permission.  I don't see a
> >>>> reason to allow my webadmin to chown su to himself...
> >>> He can't do that unless he owns su (or that itself is subject to
> >>> fowner).  And chown'ing or writing to a suid app clears the suid bit
> >>> forcibly. 
> >>>
> >>> Come on, guys, you can do better.
> >>>
> >> This hole discussion has actually opened me up to a new understanding.
> >> SELinux right now does not prevent the execution of setuid applications
> >> if you do not have setuid capability, it only prevents you from running
> >> apps that actually execute the setuid() call.
> >>
> >> I think this is a problem.  One of the things I have been saying in my
> >> presentations is that running as staff_t will prevent you from running
> >> any setuid application unless a transition is defined.  Turns out this
> >> is wrong and I was lying.
> >>
> >> # cp /usr/bin/id /usr/bin/myid
> >> # chmod 4755 /usr/bin/myid
> >>
> >> $ myid
> >> uid=3267(dwalsh) gid=3267(dwalsh) euid=0(root) groups=3267(dwalsh)
> >> context=staff_u:staff_r:staff_t:s0
> >>
> >> So running a chmod o+s file as staff_t will run as EUID 0.  I think this
> >> is something SELinux should block.  At least treat this the same way a
> >> file system mounted nosetuid would.
> > 
> > That would require a control on the exec path instead of chmod/setattr -
> > which is what I suggested a year ago in response to the original RFC.
> > 
> Sounds like a good idea, I guess you should have pushed it.  :^)
> 
> > But note that gaining EUID 0 does not automatically grant privilege
> > under SELinux - your capabilities are still limited based on domain and
> > your ability to read/write even root-owned files is controlled based on
> > the (domain, type, file class) triple.
> > 
> 
> Understood.  But we still have the risc of having a fairly wide open
> user type like staff_t tripping on a setuid app that could exculate
> privs.  Or the ability for two staff_t users to attach each other
> through setuid apps.

Ok, then I think the path forward is:
- a setsuid file permission check only applied when setting suid/sgid in
selinux_inode_setattr (and maybe when adding wider execute access,
although that's harder if you want to take ACLs into account),

- a new process permission check in selinux_bprm_set_security() when
bprm->e_uid != current->euid or bprm->e_gid != current->egid or !
cap_issubset(bprm->cap_post_exec_permitted, current->cap_permitted).

The first one controls what processes can create new entrypoints into a
uid/gid.  The second one controls the ability to invoke a suid/sgid or
file-caps program at all.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-20 20:04                       ` Stephen Smalley
@ 2008-10-20 20:12                         ` Eric Paris
  2008-10-20 20:24                           ` Stephen Smalley
  0 siblings, 1 reply; 23+ messages in thread
From: Eric Paris @ 2008-10-20 20:12 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Daniel J Walsh, Eric Paris, selinux, jmorris, sgrubb

On Mon, Oct 20, 2008 at 4:04 PM, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On Mon, 2008-10-20 at 15:25 -0400, Daniel J Walsh wrote:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>> Stephen Smalley wrote:
>> > On Fri, 2008-10-17 at 17:18 -0400, Daniel J Walsh wrote:
>> >> -----BEGIN PGP SIGNED MESSAGE-----
>> >> Hash: SHA1
>> >>
>> >> Stephen Smalley wrote:
>> >>> On Fri, 2008-10-17 at 16:04 -0400, Eric Paris wrote:
>> >>>> On Fri, 2008-10-17 at 15:39 -0400, Stephen Smalley wrote:
>> >>>>
>> >>>>> I don't follow the above.  First, the CAP_SETUID capability controls the
>> >>>>> ability to use set*uid() system calls, not to execute setuid binaries
>> >>>>> (aside from a special case for shared state).  Second, if some other
>> >>>>> confined domain executes a setuid binary created by this user, it is
>> >>>>> still limited by the permissions granted to that original confined
>> >>>>> domain as far as SELinux is concerned.
>> >>>> He's saying there are almost 200 domains that can run setuid apps.
>> >>> As I said, CAP_SETUID isn't about whether or not you can run a setuid
>> >>> app.  You can do that without CAP_SETUID.  Obviously since a normal
>> >>> unprivileged user shell can run a setuid program in the first place.
>> >>>
>> >>>> Limiting the number of domains that can create new setuid apps limits
>> >>>> the number of places that these domains can go.  Clearly they are all
>> >>>> still confined to their domain and whatever it allows, but allowing them
>> >>>> to gain root priveledges may give them the ability to attack other parts
>> >>> Wait - how did they gain root privileges?  root privileges are
>> >>> capabilities, and we control capabilities based on domain.
>> >>>
>> >>>> of the system normally controlled by dac.  This certainly doesn't lessen
>> >>>> the MAC confinement.  Lets assume an audited system in which we are
>> >>>> certain the only suid app untrusted users are allowed to run is ping.
>> >>>> So the users have the right to run suid apps.  They are protected from
>> >>>> each other by DAC.
>> >>>>
>> >>>> Confined webadmin writes a program which is clears out other users
>> >>>> public_html when they get a spurious DMCA takedown notice.  He then
>> >>>> (because he is a lazy bumbling idiot) makes his script suid so he does
>> >>>> not have to go into his confined webadmin account constantly to delete
>> >>>> users webpages.
>> >>> He could also make a daemon that runs under his uid and accepts commands
>> >>> via local socket.
>> >>>
>> >>>> Normal DAC protects user2 from being attacked by user1.  Because of the
>> >>>> bumbling incompetance of confined webadmin user1 can now use this setuid
>> >>>> app to do things which he is allow by selinux policy but denied by
>> >>>> normal DAC permissions.
>> >>>>
>> >>>> Why did webadmin need to make a setuid app to begin with?  file caps are
>> >>>> already protected by CAP_SETFCAP.  Lets assume system policy says that
>> >>>> su should not be setuid.  Should the webadmin really be allowed to
>> >>>> easily override that system policy because he wants to use su - to get
>> >>>> to his confined domain instead of sudo?
>> >>> He can't get to his confined domain via some other program unless policy
>> >>> says he can.  He can only get to some other uid that way.
>> >>>
>> >>>>   She bumbling idiot really be
>> >>>> allowed to say add o+x to su - when the system policy only really wanted
>> >>>> group wheel to be able to run su?  Should the bumbling idiot be able to
>> >>>> remove the suid flag from a program and not be able to fix it?
>> >>>>
>> >>>> I think there are some real gains that can be made by limiting how
>> >>>> confined admins or untrusted users can deal with suid apps.
>> >>>>
>> >>>> I'd probably be inclined to add changing the uid/gid/other things that
>> >>>> clear setuid to be things which require this permission.  I don't see a
>> >>>> reason to allow my webadmin to chown su to himself...
>> >>> He can't do that unless he owns su (or that itself is subject to
>> >>> fowner).  And chown'ing or writing to a suid app clears the suid bit
>> >>> forcibly.
>> >>>
>> >>> Come on, guys, you can do better.
>> >>>
>> >> This hole discussion has actually opened me up to a new understanding.
>> >> SELinux right now does not prevent the execution of setuid applications
>> >> if you do not have setuid capability, it only prevents you from running
>> >> apps that actually execute the setuid() call.
>> >>
>> >> I think this is a problem.  One of the things I have been saying in my
>> >> presentations is that running as staff_t will prevent you from running
>> >> any setuid application unless a transition is defined.  Turns out this
>> >> is wrong and I was lying.
>> >>
>> >> # cp /usr/bin/id /usr/bin/myid
>> >> # chmod 4755 /usr/bin/myid
>> >>
>> >> $ myid
>> >> uid=3267(dwalsh) gid=3267(dwalsh) euid=0(root) groups=3267(dwalsh)
>> >> context=staff_u:staff_r:staff_t:s0
>> >>
>> >> So running a chmod o+s file as staff_t will run as EUID 0.  I think this
>> >> is something SELinux should block.  At least treat this the same way a
>> >> file system mounted nosetuid would.
>> >
>> > That would require a control on the exec path instead of chmod/setattr -
>> > which is what I suggested a year ago in response to the original RFC.
>> >
>> Sounds like a good idea, I guess you should have pushed it.  :^)
>>
>> > But note that gaining EUID 0 does not automatically grant privilege
>> > under SELinux - your capabilities are still limited based on domain and
>> > your ability to read/write even root-owned files is controlled based on
>> > the (domain, type, file class) triple.
>> >
>>
>> Understood.  But we still have the risc of having a fairly wide open
>> user type like staff_t tripping on a setuid app that could exculate
>> privs.  Or the ability for two staff_t users to attach each other
>> through setuid apps.
>
> Ok, then I think the path forward is:
> - a setsuid file permission check only applied when setting suid/sgid in
> selinux_inode_setattr (and maybe when adding wider execute access,
> although that's harder if you want to take ACLs into account),
>
> - a new process permission check in selinux_bprm_set_security() when
> bprm->e_uid != current->euid or bprm->e_gid != current->egid or !
> cap_issubset(bprm->cap_post_exec_permitted, current->cap_permitted).

I'll take a look.  At that point is current->cap_permitted still that
of the original execve process or has it already been intersected with
cap_inheritable....   /me has spent all day looking at how to audit
fcaps and I realized I got that wrong the first time...

-Eric

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-20 20:12                         ` Eric Paris
@ 2008-10-20 20:24                           ` Stephen Smalley
  2008-10-20 20:27                             ` Stephen Smalley
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2008-10-20 20:24 UTC (permalink / raw)
  To: Eric Paris; +Cc: Daniel J Walsh, Eric Paris, selinux, jmorris, sgrubb

On Mon, 2008-10-20 at 16:12 -0400, Eric Paris wrote:
> On Mon, Oct 20, 2008 at 4:04 PM, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> > On Mon, 2008-10-20 at 15:25 -0400, Daniel J Walsh wrote:
> >> -----BEGIN PGP SIGNED MESSAGE-----
> >> Hash: SHA1
> >>
> >> Stephen Smalley wrote:
> >> > On Fri, 2008-10-17 at 17:18 -0400, Daniel J Walsh wrote:
> >> >> -----BEGIN PGP SIGNED MESSAGE-----
> >> >> Hash: SHA1
> >> >>
> >> >> Stephen Smalley wrote:
> >> >>> On Fri, 2008-10-17 at 16:04 -0400, Eric Paris wrote:
> >> >>>> On Fri, 2008-10-17 at 15:39 -0400, Stephen Smalley wrote:
> >> >>>>
> >> >>>>> I don't follow the above.  First, the CAP_SETUID capability controls the
> >> >>>>> ability to use set*uid() system calls, not to execute setuid binaries
> >> >>>>> (aside from a special case for shared state).  Second, if some other
> >> >>>>> confined domain executes a setuid binary created by this user, it is
> >> >>>>> still limited by the permissions granted to that original confined
> >> >>>>> domain as far as SELinux is concerned.
> >> >>>> He's saying there are almost 200 domains that can run setuid apps.
> >> >>> As I said, CAP_SETUID isn't about whether or not you can run a setuid
> >> >>> app.  You can do that without CAP_SETUID.  Obviously since a normal
> >> >>> unprivileged user shell can run a setuid program in the first place.
> >> >>>
> >> >>>> Limiting the number of domains that can create new setuid apps limits
> >> >>>> the number of places that these domains can go.  Clearly they are all
> >> >>>> still confined to their domain and whatever it allows, but allowing them
> >> >>>> to gain root priveledges may give them the ability to attack other parts
> >> >>> Wait - how did they gain root privileges?  root privileges are
> >> >>> capabilities, and we control capabilities based on domain.
> >> >>>
> >> >>>> of the system normally controlled by dac.  This certainly doesn't lessen
> >> >>>> the MAC confinement.  Lets assume an audited system in which we are
> >> >>>> certain the only suid app untrusted users are allowed to run is ping.
> >> >>>> So the users have the right to run suid apps.  They are protected from
> >> >>>> each other by DAC.
> >> >>>>
> >> >>>> Confined webadmin writes a program which is clears out other users
> >> >>>> public_html when they get a spurious DMCA takedown notice.  He then
> >> >>>> (because he is a lazy bumbling idiot) makes his script suid so he does
> >> >>>> not have to go into his confined webadmin account constantly to delete
> >> >>>> users webpages.
> >> >>> He could also make a daemon that runs under his uid and accepts commands
> >> >>> via local socket.
> >> >>>
> >> >>>> Normal DAC protects user2 from being attacked by user1.  Because of the
> >> >>>> bumbling incompetance of confined webadmin user1 can now use this setuid
> >> >>>> app to do things which he is allow by selinux policy but denied by
> >> >>>> normal DAC permissions.
> >> >>>>
> >> >>>> Why did webadmin need to make a setuid app to begin with?  file caps are
> >> >>>> already protected by CAP_SETFCAP.  Lets assume system policy says that
> >> >>>> su should not be setuid.  Should the webadmin really be allowed to
> >> >>>> easily override that system policy because he wants to use su - to get
> >> >>>> to his confined domain instead of sudo?
> >> >>> He can't get to his confined domain via some other program unless policy
> >> >>> says he can.  He can only get to some other uid that way.
> >> >>>
> >> >>>>   She bumbling idiot really be
> >> >>>> allowed to say add o+x to su - when the system policy only really wanted
> >> >>>> group wheel to be able to run su?  Should the bumbling idiot be able to
> >> >>>> remove the suid flag from a program and not be able to fix it?
> >> >>>>
> >> >>>> I think there are some real gains that can be made by limiting how
> >> >>>> confined admins or untrusted users can deal with suid apps.
> >> >>>>
> >> >>>> I'd probably be inclined to add changing the uid/gid/other things that
> >> >>>> clear setuid to be things which require this permission.  I don't see a
> >> >>>> reason to allow my webadmin to chown su to himself...
> >> >>> He can't do that unless he owns su (or that itself is subject to
> >> >>> fowner).  And chown'ing or writing to a suid app clears the suid bit
> >> >>> forcibly.
> >> >>>
> >> >>> Come on, guys, you can do better.
> >> >>>
> >> >> This hole discussion has actually opened me up to a new understanding.
> >> >> SELinux right now does not prevent the execution of setuid applications
> >> >> if you do not have setuid capability, it only prevents you from running
> >> >> apps that actually execute the setuid() call.
> >> >>
> >> >> I think this is a problem.  One of the things I have been saying in my
> >> >> presentations is that running as staff_t will prevent you from running
> >> >> any setuid application unless a transition is defined.  Turns out this
> >> >> is wrong and I was lying.
> >> >>
> >> >> # cp /usr/bin/id /usr/bin/myid
> >> >> # chmod 4755 /usr/bin/myid
> >> >>
> >> >> $ myid
> >> >> uid=3267(dwalsh) gid=3267(dwalsh) euid=0(root) groups=3267(dwalsh)
> >> >> context=staff_u:staff_r:staff_t:s0
> >> >>
> >> >> So running a chmod o+s file as staff_t will run as EUID 0.  I think this
> >> >> is something SELinux should block.  At least treat this the same way a
> >> >> file system mounted nosetuid would.
> >> >
> >> > That would require a control on the exec path instead of chmod/setattr -
> >> > which is what I suggested a year ago in response to the original RFC.
> >> >
> >> Sounds like a good idea, I guess you should have pushed it.  :^)
> >>
> >> > But note that gaining EUID 0 does not automatically grant privilege
> >> > under SELinux - your capabilities are still limited based on domain and
> >> > your ability to read/write even root-owned files is controlled based on
> >> > the (domain, type, file class) triple.
> >> >
> >>
> >> Understood.  But we still have the risc of having a fairly wide open
> >> user type like staff_t tripping on a setuid app that could exculate
> >> privs.  Or the ability for two staff_t users to attach each other
> >> through setuid apps.
> >
> > Ok, then I think the path forward is:
> > - a setsuid file permission check only applied when setting suid/sgid in
> > selinux_inode_setattr (and maybe when adding wider execute access,
> > although that's harder if you want to take ACLs into account),
> >
> > - a new process permission check in selinux_bprm_set_security() when
> > bprm->e_uid != current->euid or bprm->e_gid != current->egid or !
> > cap_issubset(bprm->cap_post_exec_permitted, current->cap_permitted).
> 
> I'll take a look.  At that point is current->cap_permitted still that
> of the original execve process or has it already been intersected with
> cap_inheritable....   /me has spent all day looking at how to audit
> fcaps and I realized I got that wrong the first time...

In selinux_bprm_set_security(), after the call to the secondary_ops
hook, we should have the new permitted set in brpm->cap_effective while
current's credentials are still those of the caller (unchanged) - the
changes are not applied until bprm_apply_creds.  The inheritable mask is
factored into the computation of bprm->cap_post_exec_permitted during
cap_bprm_set_security.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-20 20:24                           ` Stephen Smalley
@ 2008-10-20 20:27                             ` Stephen Smalley
  0 siblings, 0 replies; 23+ messages in thread
From: Stephen Smalley @ 2008-10-20 20:27 UTC (permalink / raw)
  To: Eric Paris; +Cc: Daniel J Walsh, Eric Paris, selinux, jmorris, sgrubb

On Mon, 2008-10-20 at 16:24 -0400, Stephen Smalley wrote:
> On Mon, 2008-10-20 at 16:12 -0400, Eric Paris wrote:
> > On Mon, Oct 20, 2008 at 4:04 PM, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> > > On Mon, 2008-10-20 at 15:25 -0400, Daniel J Walsh wrote:
> > >> -----BEGIN PGP SIGNED MESSAGE-----
> > >> Hash: SHA1
> > >>
> > >> Stephen Smalley wrote:
> > >> > On Fri, 2008-10-17 at 17:18 -0400, Daniel J Walsh wrote:
> > >> >> -----BEGIN PGP SIGNED MESSAGE-----
> > >> >> Hash: SHA1
> > >> >>
> > >> >> Stephen Smalley wrote:
> > >> >>> On Fri, 2008-10-17 at 16:04 -0400, Eric Paris wrote:
> > >> >>>> On Fri, 2008-10-17 at 15:39 -0400, Stephen Smalley wrote:
> > >> >>>>
> > >> >>>>> I don't follow the above.  First, the CAP_SETUID capability controls the
> > >> >>>>> ability to use set*uid() system calls, not to execute setuid binaries
> > >> >>>>> (aside from a special case for shared state).  Second, if some other
> > >> >>>>> confined domain executes a setuid binary created by this user, it is
> > >> >>>>> still limited by the permissions granted to that original confined
> > >> >>>>> domain as far as SELinux is concerned.
> > >> >>>> He's saying there are almost 200 domains that can run setuid apps.
> > >> >>> As I said, CAP_SETUID isn't about whether or not you can run a setuid
> > >> >>> app.  You can do that without CAP_SETUID.  Obviously since a normal
> > >> >>> unprivileged user shell can run a setuid program in the first place.
> > >> >>>
> > >> >>>> Limiting the number of domains that can create new setuid apps limits
> > >> >>>> the number of places that these domains can go.  Clearly they are all
> > >> >>>> still confined to their domain and whatever it allows, but allowing them
> > >> >>>> to gain root priveledges may give them the ability to attack other parts
> > >> >>> Wait - how did they gain root privileges?  root privileges are
> > >> >>> capabilities, and we control capabilities based on domain.
> > >> >>>
> > >> >>>> of the system normally controlled by dac.  This certainly doesn't lessen
> > >> >>>> the MAC confinement.  Lets assume an audited system in which we are
> > >> >>>> certain the only suid app untrusted users are allowed to run is ping.
> > >> >>>> So the users have the right to run suid apps.  They are protected from
> > >> >>>> each other by DAC.
> > >> >>>>
> > >> >>>> Confined webadmin writes a program which is clears out other users
> > >> >>>> public_html when they get a spurious DMCA takedown notice.  He then
> > >> >>>> (because he is a lazy bumbling idiot) makes his script suid so he does
> > >> >>>> not have to go into his confined webadmin account constantly to delete
> > >> >>>> users webpages.
> > >> >>> He could also make a daemon that runs under his uid and accepts commands
> > >> >>> via local socket.
> > >> >>>
> > >> >>>> Normal DAC protects user2 from being attacked by user1.  Because of the
> > >> >>>> bumbling incompetance of confined webadmin user1 can now use this setuid
> > >> >>>> app to do things which he is allow by selinux policy but denied by
> > >> >>>> normal DAC permissions.
> > >> >>>>
> > >> >>>> Why did webadmin need to make a setuid app to begin with?  file caps are
> > >> >>>> already protected by CAP_SETFCAP.  Lets assume system policy says that
> > >> >>>> su should not be setuid.  Should the webadmin really be allowed to
> > >> >>>> easily override that system policy because he wants to use su - to get
> > >> >>>> to his confined domain instead of sudo?
> > >> >>> He can't get to his confined domain via some other program unless policy
> > >> >>> says he can.  He can only get to some other uid that way.
> > >> >>>
> > >> >>>>   She bumbling idiot really be
> > >> >>>> allowed to say add o+x to su - when the system policy only really wanted
> > >> >>>> group wheel to be able to run su?  Should the bumbling idiot be able to
> > >> >>>> remove the suid flag from a program and not be able to fix it?
> > >> >>>>
> > >> >>>> I think there are some real gains that can be made by limiting how
> > >> >>>> confined admins or untrusted users can deal with suid apps.
> > >> >>>>
> > >> >>>> I'd probably be inclined to add changing the uid/gid/other things that
> > >> >>>> clear setuid to be things which require this permission.  I don't see a
> > >> >>>> reason to allow my webadmin to chown su to himself...
> > >> >>> He can't do that unless he owns su (or that itself is subject to
> > >> >>> fowner).  And chown'ing or writing to a suid app clears the suid bit
> > >> >>> forcibly.
> > >> >>>
> > >> >>> Come on, guys, you can do better.
> > >> >>>
> > >> >> This hole discussion has actually opened me up to a new understanding.
> > >> >> SELinux right now does not prevent the execution of setuid applications
> > >> >> if you do not have setuid capability, it only prevents you from running
> > >> >> apps that actually execute the setuid() call.
> > >> >>
> > >> >> I think this is a problem.  One of the things I have been saying in my
> > >> >> presentations is that running as staff_t will prevent you from running
> > >> >> any setuid application unless a transition is defined.  Turns out this
> > >> >> is wrong and I was lying.
> > >> >>
> > >> >> # cp /usr/bin/id /usr/bin/myid
> > >> >> # chmod 4755 /usr/bin/myid
> > >> >>
> > >> >> $ myid
> > >> >> uid=3267(dwalsh) gid=3267(dwalsh) euid=0(root) groups=3267(dwalsh)
> > >> >> context=staff_u:staff_r:staff_t:s0
> > >> >>
> > >> >> So running a chmod o+s file as staff_t will run as EUID 0.  I think this
> > >> >> is something SELinux should block.  At least treat this the same way a
> > >> >> file system mounted nosetuid would.
> > >> >
> > >> > That would require a control on the exec path instead of chmod/setattr -
> > >> > which is what I suggested a year ago in response to the original RFC.
> > >> >
> > >> Sounds like a good idea, I guess you should have pushed it.  :^)
> > >>
> > >> > But note that gaining EUID 0 does not automatically grant privilege
> > >> > under SELinux - your capabilities are still limited based on domain and
> > >> > your ability to read/write even root-owned files is controlled based on
> > >> > the (domain, type, file class) triple.
> > >> >
> > >>
> > >> Understood.  But we still have the risc of having a fairly wide open
> > >> user type like staff_t tripping on a setuid app that could exculate
> > >> privs.  Or the ability for two staff_t users to attach each other
> > >> through setuid apps.
> > >
> > > Ok, then I think the path forward is:
> > > - a setsuid file permission check only applied when setting suid/sgid in
> > > selinux_inode_setattr (and maybe when adding wider execute access,
> > > although that's harder if you want to take ACLs into account),
> > >
> > > - a new process permission check in selinux_bprm_set_security() when
> > > bprm->e_uid != current->euid or bprm->e_gid != current->egid or !
> > > cap_issubset(bprm->cap_post_exec_permitted, current->cap_permitted).
> > 
> > I'll take a look.  At that point is current->cap_permitted still that
> > of the original execve process or has it already been intersected with
> > cap_inheritable....   /me has spent all day looking at how to audit
> > fcaps and I realized I got that wrong the first time...
> 
> In selinux_bprm_set_security(), after the call to the secondary_ops
> hook, we should have the new permitted set in brpm->cap_effective while

Sorry - s/cap_effective/cap_post_exec_permitted/

> current's credentials are still those of the caller (unchanged) - the
> changes are not applied until bprm_apply_creds.  The inheritable mask is
> factored into the computation of bprm->cap_post_exec_permitted during
> cap_bprm_set_security.
> 
-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] selinux: new permission for chmod on suid or sgid files
  2008-10-20 19:40             ` Daniel J Walsh
@ 2008-10-20 22:52               ` James Morris
  0 siblings, 0 replies; 23+ messages in thread
From: James Morris @ 2008-10-20 22:52 UTC (permalink / raw)
  To: Daniel J Walsh; +Cc: Stephen Smalley, Eric Paris, selinux, sgrubb

On Mon, 20 Oct 2008, Daniel J Walsh wrote:


> Fine, I don't care about this either.  So setting the setuid bit on
> would be the only thing we watch.

Can you guys please trim your replies?  It's not much fun scrolling 
through 14K of quoted email at nine levels of indentation just to read two 
lines of actual content.

Thanks,


- James
-- 
James Morris
<jmorris@namei.org>

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2008-10-20 22:52 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-17 15:40 [PATCH] selinux: new permission for chmod on suid or sgid files Eric Paris
2008-10-17 16:52 ` Stephen Smalley
2008-10-17 17:24   ` Stephen Smalley
2008-10-17 18:43     ` Daniel J Walsh
2008-10-17 18:53       ` Stephen Smalley
2008-10-17 19:10         ` Daniel J Walsh
2008-10-17 19:39           ` Stephen Smalley
2008-10-17 20:04             ` Eric Paris
2008-10-17 20:09               ` Stephen Smalley
2008-10-17 20:38                 ` Eric Paris
2008-10-17 20:49                   ` Eric Paris
2008-10-20 12:30                   ` Stephen Smalley
2008-10-17 21:18                 ` Daniel J Walsh
2008-10-20 12:27                   ` Stephen Smalley
2008-10-20 19:25                     ` Daniel J Walsh
2008-10-20 20:04                       ` Stephen Smalley
2008-10-20 20:12                         ` Eric Paris
2008-10-20 20:24                           ` Stephen Smalley
2008-10-20 20:27                             ` Stephen Smalley
2008-10-17 20:50         ` Daniel J Walsh
2008-10-20 12:26           ` Stephen Smalley
2008-10-20 19:40             ` Daniel J Walsh
2008-10-20 22:52               ` James Morris

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.