Skip to contentSkip to conversation

staging: lustre: validate size in ll_setxattr()

PATCH Superseded Dan Carpenter 2 participants 4 messages Oct 22, 2014

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

PATCH 2/2 staging: lustre: validate size in ll_setxattr()

If size is smaller than the lov_user_md struct then we are reading beyond the end of the buffer. I guess this is an information leak or it could cause an Oops if the memory is not mapped.

---
This was discovered through a code audit. I'm not terribly familiar with this code and I haven't tested it. Please review it carefully.

drivers/staging/lustre/lustre/llite/xattr.c +3 -0
index 252a619..75abb97 100644
@@ -223,6 +223,9 @@ int ll_setxattr(struct dentry *dentry, const char *name,
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
 	       inode->i_ino, inode->i_generation, inode, name);
 
+	if (size != 0 && size < sizeof(struct lov_user_md))
+		return -EINVAL;
+
 	ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1);
 
 	if ((strncmp(name, XATTR_TRUSTED_PREFIX,
#1 lore raw
Quoted 5 lines · Andrew Perepechko

Hi Dan!

You probably meant putting that check after the followring if-statement, since generic extended attributes can have size 1, 2, 3, ...

Ok.

Quoted 2 lines

In that case, size = 0 seems to be the wrong value size for an lov param as well.

I don't know about this. The code is very clear that size = 0 is acceptable inside the if statement. Oleg?

regards,
dan carpenter

#2 lore raw
In reply to Dan Carpenter

Hello!

Quoted 4 lines · Dan Carpenter
Quoted 2 lines

In that case, size = 0 seems to be the wrong value size for an lov param as well.

I don't know about this. The code is very clear that size = 0 is acceptable inside the if statement. Oleg?

I am not sure what if statement do you mean?
If it's the "if ((strncmp(name, XATTR_TRUSTED_PREFIX," one then size of 0 does seem to be incorrect:

                struct lov_user_md *lump = (struct lov_user_md *)value; 
// (I hope this is not a user pointer?)
…
                if (lump != NULL && lump->lmm_stripe_offset = 0)
                        lump->lmm_stripe_offset = -1;
// So, if lump is 0, we are already accessing past allowed range
…
                        int lum_size = (lump->lmm_magic = LOV_USER_MAGIC_V1) ?

and again…

Bye,
Oleg

--
To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#3 lore raw
In reply to Dan Carpenter
Quoted 8 lines · Oleg

Hello!

Quoted 4 lines · Dan Carpenter
Quoted 2 lines

In that case, size = 0 seems to be the wrong value size for an lov param as well.

I don't know about this. The code is very clear that size = 0 is acceptable inside the if statement. Oleg?

Quoted 6 lines

I am not sure what if statement do you mean?
If it's the "if ((strncmp(name, XATTR_TRUSTED_PREFIX," one then size of 0 does seem to be incorrect:

                struct lov_user_md *lump = (struct lov_user_md *)value; 

// (I hope this is not a user pointer?)

It's not.

Quoted 4 lines

…

                if (lump != NULL && lump->lmm_stripe_offset = 0)
                        lump->lmm_stripe_offset = -1;

// So, if lump is 0, we are already accessing past allowed range

If size is zero then lump is NULL and the existing code is very careful to test for that and avoid NULL dereferences. I think that Andrew is saying at it doesn't make sense for lump to be NULL.

Anyway, let me send a v2 which fixes the bug and leaves lump = NULL as is.

regards,
dan carpenter

--
To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html