Commit b500ce8d authored by Ahmed S. Darwish's avatar Ahmed S. Darwish Committed by Linus Torvalds

smackfs: do not trust `count' in inodes write()s

Smackfs write() implementation does not put a higher bound on the number of
bytes to copy from user-space.  This may lead to a DOS attack if a malicious
`count' field is given.

Assure that given `count' is exactly the length needed for a /smack/load rule.
 In case of /smack/cipso where the length is relative, assure that `count'
does not exceed the size needed for a buffer representing maximum possible
number of CIPSO 2.2 categories.
Signed-off-by: default avatarAhmed S. Darwish <darwish.07@gmail.com>
Acked-by: default avatarCasey Schaufler <casey@schaufler-ca.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 93d74463
...@@ -26,14 +26,6 @@ ...@@ -26,14 +26,6 @@
#define SMK_MAXLEN 23 #define SMK_MAXLEN 23
#define SMK_LABELLEN (SMK_MAXLEN+1) #define SMK_LABELLEN (SMK_MAXLEN+1)
/*
* How many kinds of access are there?
* Here's your answer.
*/
#define SMK_ACCESSDASH '-'
#define SMK_ACCESSLOW "rwxa"
#define SMK_ACCESSKINDS (sizeof(SMK_ACCESSLOW) - 1)
struct superblock_smack { struct superblock_smack {
char *smk_root; char *smk_root;
char *smk_floor; char *smk_floor;
......
...@@ -81,10 +81,23 @@ static struct semaphore smack_write_sem; ...@@ -81,10 +81,23 @@ static struct semaphore smack_write_sem;
/* /*
* Values for parsing cipso rules * Values for parsing cipso rules
* SMK_DIGITLEN: Length of a digit field in a rule. * SMK_DIGITLEN: Length of a digit field in a rule.
* SMK_CIPSOMEN: Minimum possible cipso rule length. * SMK_CIPSOMIN: Minimum possible cipso rule length.
* SMK_CIPSOMAX: Maximum possible cipso rule length.
*/ */
#define SMK_DIGITLEN 4 #define SMK_DIGITLEN 4
#define SMK_CIPSOMIN (SMK_MAXLEN + 2 * SMK_DIGITLEN) #define SMK_CIPSOMIN (SMK_LABELLEN + 2 * SMK_DIGITLEN)
#define SMK_CIPSOMAX (SMK_CIPSOMIN + SMACK_CIPSO_MAXCATNUM * SMK_DIGITLEN)
/*
* Values for parsing MAC rules
* SMK_ACCESS: Maximum possible combination of access permissions
* SMK_ACCESSLEN: Maximum length for a rule access field
* SMK_LOADLEN: Smack rule length
*/
#define SMK_ACCESS "rwxa"
#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
/* /*
* Seq_file read operations for /smack/load * Seq_file read operations for /smack/load
...@@ -229,14 +242,10 @@ static void smk_set_access(struct smack_rule *srp) ...@@ -229,14 +242,10 @@ static void smk_set_access(struct smack_rule *srp)
* The format is exactly: * The format is exactly:
* char subject[SMK_LABELLEN] * char subject[SMK_LABELLEN]
* char object[SMK_LABELLEN] * char object[SMK_LABELLEN]
* char access[SMK_ACCESSKINDS] * char access[SMK_ACCESSLEN]
*
* Anything following is commentary and ignored.
* *
* writes must be SMK_LABELLEN+SMK_LABELLEN+4 bytes. * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes.
*/ */
#define MINIMUM_LOAD (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSKINDS)
static ssize_t smk_write_load(struct file *file, const char __user *buf, static ssize_t smk_write_load(struct file *file, const char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
...@@ -253,7 +262,7 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf, ...@@ -253,7 +262,7 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
return -EPERM; return -EPERM;
if (*ppos != 0) if (*ppos != 0)
return -EINVAL; return -EINVAL;
if (count < MINIMUM_LOAD) if (count != SMK_LOADLEN)
return -EINVAL; return -EINVAL;
data = kzalloc(count, GFP_KERNEL); data = kzalloc(count, GFP_KERNEL);
...@@ -513,7 +522,7 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf, ...@@ -513,7 +522,7 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
return -EPERM; return -EPERM;
if (*ppos != 0) if (*ppos != 0)
return -EINVAL; return -EINVAL;
if (count <= SMK_CIPSOMIN) if (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX)
return -EINVAL; return -EINVAL;
data = kzalloc(count + 1, GFP_KERNEL); data = kzalloc(count + 1, GFP_KERNEL);
...@@ -547,7 +556,7 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf, ...@@ -547,7 +556,7 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM) if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
goto out; goto out;
if (count <= (SMK_CIPSOMIN + catlen * SMK_DIGITLEN)) if (count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
goto out; goto out;
memset(mapcatset, 0, sizeof(mapcatset)); memset(mapcatset, 0, sizeof(mapcatset));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment