Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -26,14 +26,6 @@
#define SMK_MAXLEN	23
#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 {
	char		*smk_root;
	char		*smk_floor;
+20 −11
Original line number Diff line number Diff line
@@ -81,10 +81,23 @@ static struct semaphore smack_write_sem;
/*
 * Values for parsing cipso rules
 * 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_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
@@ -229,14 +242,10 @@ static void smk_set_access(struct smack_rule *srp)
 * The format is exactly:
 *     char subject[SMK_LABELLEN]
 *     char object[SMK_LABELLEN]
 *     char access[SMK_ACCESSKINDS]
 *
 *     Anything following is commentary and ignored.
 *     char access[SMK_ACCESSLEN]
 *
 * 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,
			      size_t count, loff_t *ppos)
{
@@ -253,7 +262,7 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
		return -EPERM;
	if (*ppos != 0)
		return -EINVAL;
	if (count < MINIMUM_LOAD)
	if (count != SMK_LOADLEN)
		return -EINVAL;

	data = kzalloc(count, GFP_KERNEL);
@@ -513,7 +522,7 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
		return -EPERM;
	if (*ppos != 0)
		return -EINVAL;
	if (count <= SMK_CIPSOMIN)
	if (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX)
		return -EINVAL;

	data = kzalloc(count + 1, GFP_KERNEL);
@@ -547,7 +556,7 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
	if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
		goto out;

	if (count <= (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
	if (count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
		goto out;

	memset(mapcatset, 0, sizeof(mapcatset));