[bug report] afs: Locally edit directory data for mkdir/create/unlink/...

David Howells dhowells at redhat.com
Fri Apr 20 04:59:05 PDT 2018


Dan Carpenter <dan.carpenter at oracle.com> wrote:

> The patch 63a4681ff39c: "afs: Locally edit directory data for
> mkdir/create/unlink/..." from Apr 6, 2018, leads to the following
> static checker warning:
> 
> 	fs/afs/dir.c:1392 afs_create()
> 	warn: 'dentry->d_name.len' is out of bounds '255' vs '15'

In this case, the static checker doesn't understand the situation
sufficiently.

>    331          memcpy(de->u.name, name->name, name->len + 1);
>                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>    332          de->u.name[name->len] = 0;
>                 ^^^^^^^^^^^^^^^^^^^^^^^^
> de->u.name is a 16 character buffer.

By the strict definition of the C type:

	union afs_xdr_dirent {
		struct {
			u8		valid;
			u8		unused[1];
			__be16		hash_next;
			__be32		vnode;
			__be32		unique;
			u8		name[16];
			u8		overflow[4];
		} u;
		u8			extended_name[32];
	} __packed;

this it true - however, it's more complicated than that.

This struct represents an individual element within the structured directory
content.  These records are fixed size and you contiguously allocate however
many of them you need to store the entire record - up to 9 for a 255-char
name.

There's an overflow buffer into which the name is allowed to overflow - as far
as I can tell it used to be that if the name transgressed into this, you had
to allocate an extension record anyway, whether or not you used it.

Also, you'll notice that the record is a union and that the other member of
the union is just an array containing an extension segment for the name.

>   1364          if (dentry->d_name.len >= AFSNAMEMAX)
>                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> Here we ensure that d_name.len is 255 or less.

That's correct.

>   1392                  afs_edit_dir_add(dvnode, &dentry->d_name, &newfid,
>                                                   ^^^^^^^^^^^^^^
> This is where the warning gets generated because 255 is more than 15.

afs_dir_edit_add() allocates however many slots it needs within a page:

	/* Work out how many slots we're going to need. */
	need_slots = round_up(12 + name->len + 1 + 4, AFS_DIR_DIRENT_SIZE);
	need_slots /= AFS_DIR_DIRENT_SIZE;

David



More information about the linux-afs mailing list