diff options
| author | Ahmed S. Darwish <darwish.07@gmail.com> | 2008-03-13 15:32:34 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-03-13 16:11:43 -0400 |
| commit | b500ce8d24d1f14426643da5f6fada28c1f60533 (patch) | |
| tree | 17b6084b29434a968f787e238548a843126e2ec3 /security | |
| parent | 93d74463d018ddf05c169ad399e62e90e0f82fc0 (diff) | |
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: Ahmed S. Darwish <darwish.07@gmail.com>
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'security')
| -rw-r--r-- | security/smack/smack.h | 8 | ||||
| -rw-r--r-- | security/smack/smackfs.c | 31 |
2 files changed, 20 insertions, 19 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h index a21a0e907ab3..62c1e982849d 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
| @@ -26,14 +26,6 @@ | |||
| 26 | #define SMK_MAXLEN 23 | 26 | #define SMK_MAXLEN 23 |
| 27 | #define SMK_LABELLEN (SMK_MAXLEN+1) | 27 | #define SMK_LABELLEN (SMK_MAXLEN+1) |
| 28 | 28 | ||
| 29 | /* | ||
| 30 | * How many kinds of access are there? | ||
| 31 | * Here's your answer. | ||
| 32 | */ | ||
| 33 | #define SMK_ACCESSDASH '-' | ||
| 34 | #define SMK_ACCESSLOW "rwxa" | ||
| 35 | #define SMK_ACCESSKINDS (sizeof(SMK_ACCESSLOW) - 1) | ||
| 36 | |||
| 37 | struct superblock_smack { | 29 | struct superblock_smack { |
| 38 | char *smk_root; | 30 | char *smk_root; |
| 39 | char *smk_floor; | 31 | char *smk_floor; |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 358c92c1a153..afe7c9b0732a 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
| @@ -81,10 +81,23 @@ static struct semaphore smack_write_sem; | |||
| 81 | /* | 81 | /* |
| 82 | * Values for parsing cipso rules | 82 | * Values for parsing cipso rules |
| 83 | * SMK_DIGITLEN: Length of a digit field in a rule. | 83 | * SMK_DIGITLEN: Length of a digit field in a rule. |
| 84 | * SMK_CIPSOMEN: Minimum possible cipso rule length. | 84 | * SMK_CIPSOMIN: Minimum possible cipso rule length. |
| 85 | * SMK_CIPSOMAX: Maximum possible cipso rule length. | ||
| 85 | */ | 86 | */ |
| 86 | #define SMK_DIGITLEN 4 | 87 | #define SMK_DIGITLEN 4 |
| 87 | #define SMK_CIPSOMIN (SMK_MAXLEN + 2 * SMK_DIGITLEN) | 88 | #define SMK_CIPSOMIN (SMK_LABELLEN + 2 * SMK_DIGITLEN) |
| 89 | #define SMK_CIPSOMAX (SMK_CIPSOMIN + SMACK_CIPSO_MAXCATNUM * SMK_DIGITLEN) | ||
| 90 | |||
| 91 | /* | ||
| 92 | * Values for parsing MAC rules | ||
| 93 | * SMK_ACCESS: Maximum possible combination of access permissions | ||
| 94 | * SMK_ACCESSLEN: Maximum length for a rule access field | ||
| 95 | * SMK_LOADLEN: Smack rule length | ||
| 96 | */ | ||
| 97 | #define SMK_ACCESS "rwxa" | ||
| 98 | #define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1) | ||
| 99 | #define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) | ||
| 100 | |||
| 88 | 101 | ||
| 89 | /* | 102 | /* |
| 90 | * Seq_file read operations for /smack/load | 103 | * Seq_file read operations for /smack/load |
| @@ -229,14 +242,10 @@ static void smk_set_access(struct smack_rule *srp) | |||
| 229 | * The format is exactly: | 242 | * The format is exactly: |
| 230 | * char subject[SMK_LABELLEN] | 243 | * char subject[SMK_LABELLEN] |
| 231 | * char object[SMK_LABELLEN] | 244 | * char object[SMK_LABELLEN] |
| 232 | * char access[SMK_ACCESSKINDS] | 245 | * char access[SMK_ACCESSLEN] |
| 233 | * | ||
| 234 | * Anything following is commentary and ignored. | ||
| 235 | * | 246 | * |
| 236 | * writes must be SMK_LABELLEN+SMK_LABELLEN+4 bytes. | 247 | * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes. |
| 237 | */ | 248 | */ |
| 238 | #define MINIMUM_LOAD (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSKINDS) | ||
| 239 | |||
| 240 | static ssize_t smk_write_load(struct file *file, const char __user *buf, | 249 | static ssize_t smk_write_load(struct file *file, const char __user *buf, |
| 241 | size_t count, loff_t *ppos) | 250 | size_t count, loff_t *ppos) |
| 242 | { | 251 | { |
| @@ -253,7 +262,7 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf, | |||
| 253 | return -EPERM; | 262 | return -EPERM; |
| 254 | if (*ppos != 0) | 263 | if (*ppos != 0) |
| 255 | return -EINVAL; | 264 | return -EINVAL; |
| 256 | if (count < MINIMUM_LOAD) | 265 | if (count != SMK_LOADLEN) |
| 257 | return -EINVAL; | 266 | return -EINVAL; |
| 258 | 267 | ||
| 259 | data = kzalloc(count, GFP_KERNEL); | 268 | data = kzalloc(count, GFP_KERNEL); |
| @@ -513,7 +522,7 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf, | |||
| 513 | return -EPERM; | 522 | return -EPERM; |
| 514 | if (*ppos != 0) | 523 | if (*ppos != 0) |
| 515 | return -EINVAL; | 524 | return -EINVAL; |
| 516 | if (count <= SMK_CIPSOMIN) | 525 | if (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX) |
| 517 | return -EINVAL; | 526 | return -EINVAL; |
| 518 | 527 | ||
| 519 | data = kzalloc(count + 1, GFP_KERNEL); | 528 | data = kzalloc(count + 1, GFP_KERNEL); |
| @@ -547,7 +556,7 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf, | |||
| 547 | if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM) | 556 | if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM) |
| 548 | goto out; | 557 | goto out; |
| 549 | 558 | ||
| 550 | if (count <= (SMK_CIPSOMIN + catlen * SMK_DIGITLEN)) | 559 | if (count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN)) |
| 551 | goto out; | 560 | goto out; |
| 552 | 561 | ||
| 553 | memset(mapcatset, 0, sizeof(mapcatset)); | 562 | memset(mapcatset, 0, sizeof(mapcatset)); |
