On Fri, Nov 7, 2014 at 8:54 PM, Chris Mason <c...@fb.com> wrote:
>
>
> On Fri, Nov 7, 2014 at 3:39 PM, Filipe Manana <fdman...@suse.com> wrote:
>>
>> Replacing a xattr consists of doing a lookup for its existing value,
>> delete
>> the current value from the respective leaf, release the search path and
>> then
>> finally insert the new value. This leaves a time window where readers
>> (getxattr,
>> listxattrs) won't see any value for the xattr. Xattrs are used to store
>> ACLs,
>> so this has security implications.
>>
>> This change also fixes 2 other existing issues which were:
>>
>> *) Deleting the old xattr value without verifying first if the new xattr
>> will
>>    fit in the existing leaf item (in case multiple xattrs are packed in
>> the
>>    same item due to name hash collision);
>>
>> *) Returning -EEXIST when the flag XATTR_CREATE is given and the xattr
>> doesn't
>>    exist but we have have an existing item that packs muliple xattrs with
>>    the same name hash as the input xattr. In this case we should return
>> ENOSPC.
>>
>> A test case for xfstests follows soon.
>>
>> Thanks to Alexandre Oliva for reporting the non-atomicity of the xattr
>> replace
>> implementation.
>
>
> Thanks Filipe, one problem:
>
>> +
>> +               if (size > old_data_len) {
>> +                       if (btrfs_leaf_free_space(root, leaf) <
>> +                           (size - old_data_len)) {
>> +                               ret = -ENOSPC;
>> +                               goto out;
>> +                       }
>>                 }
>
>
> This means replacing an xattr item can fail if the leaf doesn't happen to
> have free space.  btrfs_search_slot already has code meant to extend the
> item, even if the item you're searching for is already found.  (see the call
> to split_leaf with extend == 1).
>
> So what you want to do is find out the current size of the item, and call
> btrfs search_slot again with that size + the extra needed for the new name.
> From there you should be able to call btrfs_extend_item like you currently
> are.

So what I do is call btrfs_seach_slot with ins_size == new_xattr_size.
If it returns -eoverflow (it couldn't extent by +new_size, which
includes the name, dir_item and btrfs_item structs), I don't return
immediately because after deleting the existing xattr we may have
enough space in the leaf (that is, we no longer to extend by new_size,
but by a smaller amount == new_size - old_size, and excluding the
name, dir_item and btrfs_item structs), effectively not requiring the
original size passed to btrfs_search_slot. So if I correctly
understood you, it's almost equivalent to your suggestion but without
releasing paths and keep retrying.

Did I miss something? :)

>
> -chris
>
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Filipe David Manana,

"Reasonable men adapt themselves to the world.
 Unreasonable men adapt the world to themselves.
 That's why all progress depends on unreasonable men."
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to