Re: [RFC PATCH] SELinux: differentiate between open and r/w operations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 2008-02-22 at 14:02 -0500, Eric Paris wrote:
> An often found problem with selinux in the wild is the use of things
> like stdout redirection to a file.  As an example it may be perfectly
> reasonable for a user to run a daemon in the foreground for debugging
> and pipe the output to a file in /tmp.  But it would unreasonable for
> that daemon to directly open a file in /tmp.  Currently SELinux sees
> both of these as the same security operation.
> 
> By separating the open permission from the r/w permission we are able to
> more broadly grant r/w permissions while still being able to see and
> stop a number of attack vectors and misbehaving programs.
> 
> ---
> 
> This patch makes use of Paul Moore's new capability map but that was
> completely untested by me.  I actually just added a new selinuxfs file
> to turn these checks on and off at will during my testing and never even
> defined the permissions in my running policy.  So to say the least
> testing is a bit short.  Does it look right to you on first glance Paul?
> 
> It did however work.  If prog1 opened a bunch of files and then execve'd
> prog2 we would have.  prog1 need open+r/w and prog2 just needs r/w.
> 
>  security/selinux/hooks.c                     |   33 +++++++++++++++++++++++++-
>  security/selinux/include/av_perm_to_string.h |    5 ++++
>  security/selinux/include/av_permissions.h    |    5 ++++
>  security/selinux/include/security.h          |    2 +
>  security/selinux/ss/services.c               |    3 ++
>  5 files changed, 47 insertions(+), 1 deletions(-)
> 
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 75c2e99..fd911fe 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -1616,6 +1616,37 @@ static inline u32 file_to_av(struct file *file)
>  	return av;
>  }
>  
> +/*
> + * Convert a Linux file to an access vector and include the correct open
> + * open permission.
> + */
> +static inline u32 open_file_to_av(struct file *file)
> +{
> +	struct inode *inode = file->f_path.dentry->d_inode;
> +	u32 av = file_to_av(file);
> +
> +	if (selinux_policycap_openperm) {
> +		/*
> +		 * lnk files and socks do not really have an 'open'
> +		 */
> +		if (S_ISREG(inode->i_mode))
> +			av |= FILE__OPEN;
> +		else if (S_ISCHR(inode->i_mode))
> +			av |= CHR_FILE__OPEN;
> +		else if (S_ISBLK(inode->i_mode))
> +			av |= BLK_FILE__OPEN;
> +		else if (S_ISFIFO(inode->i_mode))
> +			av |= FIFO_FILE__OPEN;
> +		else if (S_ISDIR(inode->i_mode))
> +			av |= DIR__OPEN;
> +		else {
> +			printk(KERN_EMERG "inside open_file_to_av with unknown mode:%x\n", inode->i_mode);
> +			BUG();
> +		}
> +	}
> +	return av;
> +}
> +
>  /* Hook functions begin here. */
>  
>  static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
> @@ -3031,7 +3062,7 @@ static int selinux_dentry_open(struct file *file)
>  	 * new inode label or new policy.
>  	 * This check is not redundant - do not remove.
>  	 */
> -	return inode_has_perm(current, inode, file_to_av(file), NULL);
> +	return inode_has_perm(current, inode, open_file_to_av(file), NULL);

Do we only want this new open permission checked in
selinux_dentry_open() or should it be checked by
selinux_inode_permission()?

selinux_inode_permission() is the original open-time check.
selinux_dentry_open() was only introduced to save state for Yuichi's
improve read/write performance patch.  It only rechecks access because
there is a small window where the saved state might have changed since
the original selinux_inode_permission() check, and we want to ensure
that we don't then fail to revalidate read/write at all.

I'd tend to think that the open check should occur in
selinux_inode_permission() and only there.


>  }
>  
>  /* task security operations */
> diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
> index d569669..1223b4f 100644
> --- a/security/selinux/include/av_perm_to_string.h
> +++ b/security/selinux/include/av_perm_to_string.h
> @@ -14,12 +14,17 @@
>     S_(SECCLASS_DIR, DIR__REPARENT, "reparent")
>     S_(SECCLASS_DIR, DIR__SEARCH, "search")
>     S_(SECCLASS_DIR, DIR__RMDIR, "rmdir")
> +   S_(SECCLASS_DIR, DIR__OPEN, "open")
>     S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans")
>     S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
>     S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
> +   S_(SECCLASS_FILE, FILE__OPEN, "open")
>     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")
> +   S_(SECCLASS_CHR_FILE, CHR_FILE__OPEN, "open")
> +   S_(SECCLASS_BLK_FILE, BLK_FILE__OPEN, "open")
> +   S_(SECCLASS_FIFO_FILE, FIFO_FILE__OPEN, "open")
>     S_(SECCLASS_FD, FD__USE, "use")
>     S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto")
>     S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn")
> diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
> index 75b4131..c4c5116 100644
> --- a/security/selinux/include/av_permissions.h
> +++ b/security/selinux/include/av_permissions.h
> @@ -79,6 +79,7 @@
>  #define DIR__REPARENT                             0x00080000UL
>  #define DIR__SEARCH                               0x00100000UL
>  #define DIR__RMDIR                                0x00200000UL
> +#define DIR__OPEN                                 0x00400000UL
>  #define FILE__IOCTL                               0x00000001UL
>  #define FILE__READ                                0x00000002UL
>  #define FILE__WRITE                               0x00000004UL
> @@ -99,6 +100,7 @@
>  #define FILE__EXECUTE_NO_TRANS                    0x00020000UL
>  #define FILE__ENTRYPOINT                          0x00040000UL
>  #define FILE__EXECMOD                             0x00080000UL
> +#define FILE__OPEN                                0x00100000UL
>  #define LNK_FILE__IOCTL                           0x00000001UL
>  #define LNK_FILE__READ                            0x00000002UL
>  #define LNK_FILE__WRITE                           0x00000004UL
> @@ -136,6 +138,7 @@
>  #define CHR_FILE__EXECUTE_NO_TRANS                0x00020000UL
>  #define CHR_FILE__ENTRYPOINT                      0x00040000UL
>  #define CHR_FILE__EXECMOD                         0x00080000UL
> +#define CHR_FILE__OPEN                            0x00100000UL
>  #define BLK_FILE__IOCTL                           0x00000001UL
>  #define BLK_FILE__READ                            0x00000002UL
>  #define BLK_FILE__WRITE                           0x00000004UL
> @@ -153,6 +156,7 @@
>  #define BLK_FILE__SWAPON                          0x00004000UL
>  #define BLK_FILE__QUOTAON                         0x00008000UL
>  #define BLK_FILE__MOUNTON                         0x00010000UL
> +#define BLK_FILE__OPEN                            0x00020000UL
>  #define SOCK_FILE__IOCTL                          0x00000001UL
>  #define SOCK_FILE__READ                           0x00000002UL
>  #define SOCK_FILE__WRITE                          0x00000004UL
> @@ -187,6 +191,7 @@
>  #define FIFO_FILE__SWAPON                         0x00004000UL
>  #define FIFO_FILE__QUOTAON                        0x00008000UL
>  #define FIFO_FILE__MOUNTON                        0x00010000UL
> +#define FIFO_FILE__OPEN                           0x00020000UL
>  #define FD__USE                                   0x00000001UL
>  #define SOCKET__IOCTL                             0x00000001UL
>  #define SOCKET__READ                              0x00000002UL
> diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
> index 837ce42..fa30f53 100644
> --- a/security/selinux/include/security.h
> +++ b/security/selinux/include/security.h
> @@ -43,11 +43,13 @@ extern int selinux_mls_enabled;
>  /* Policy capabilities */
>  enum {
>  	POLICYDB_CAPABILITY_NETPEER,
> +	POLICYDB_CAPABILITY_OPENPERM,
>  	__POLICYDB_CAPABILITY_MAX
>  };
>  #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
>  
>  extern int selinux_policycap_netpeer;
> +extern int selinux_policycap_openperm;
>  
>  int security_load_policy(void * data, size_t len);
>  
> diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> index f374186..23a61f1 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -61,6 +61,7 @@ extern void selnl_notify_policyload(u32 seqno);
>  unsigned int policydb_loaded_version;
>  
>  int selinux_policycap_netpeer;
> +int selinux_policycap_openperm;
>  
>  /*
>   * This is declared in avc.c
> @@ -1306,6 +1307,8 @@ static void security_load_policycaps(void)
>  {
>  	selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
>  						  POLICYDB_CAPABILITY_NETPEER);
> +	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
> +						  POLICYDB_CAPABILITY_OPENPERM);
>  }
>  
>  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@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux