Re: [PATCH RFC V1] hfsplus: Correct usage of HFSPLUS_ATTR_MAX_STRLEN for non-English attributes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Anton,

Thanks again for a rather thoughtful review.

I do completely agree, that the bound checks are almost completely useless before and after - before
the change they were simply wrong, after the change they are simply doing twice the work, just earlier.

There is no need to do twice the work - if hfsplus_asc2uni() works correctly, and failures are caught properly,
there is no need to try() it first. So that's why I simply removed the one in hfsplus_attr_build_key(),since
the check happens immediately before the actual call. It is definitely stupid doing a try() then immediately
the real thing.

But there is one advantage of doing it early - assuming try() is cheap (may or may not be the case):
the real hfsplus_asc2uni() is buried quite a lot further after setting up the atttribute B-tree for
searches, etc. So by the time the actual call happens, throwing away all that work B-tree
find_init, etc might be wasteful; besides that stuff also have mutex locks around it, etc, so
unwinding and catch errors there may not be as easy.  

In principle, I agree that if any error from hfsplus_asc2uni() is checked and caught, there
is no need to do a try() first; the practical dificulty is just that the real
hfsplus_asc2uni() is buried rather deep, and within at least one mutex lock.

So I did think about the first approach you suggested, just thought it is much harder
- the current patch is just too boring and not doing anything risky, so it is safe to use. I think the
2nd approach (keeping the try() result) would get around my worry about that mutex lock, so
I may look into that.

Now I have an "tedious, slow but working correctly how it should be" patch, for reference, and
it is a good thing to have. - it is quite educational to try to use all 127 unicode character
limit of the attribute - and not possible to do that in a UTF-8 locale. Both the userland tools (xttr)
and many of the other file systems have a 255 byte limit for EA's (in nls, and 127
unicode char can be as bad as 127 x 3 = 381 in UTF-8). I had to use an explicit nls=<not-utf-8>
mount option and run my terminal/content at a different encoding to fully use
that 127 unit storage.

When a Mac user had already written an unusually long attribute, and we try to
read it under linux - it currently (without this patch) gives a scary I/O error. That's
really not good.

i have thought of a genuine (mis-) use of non-english attributes. All the english
alphabets have their "half/full-width" equivalent at a higher
code point. ( http://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms ).
It is entirely possible for a japanese person to be typing what he thought
is english, and looks like english, and read like english - only stretched out
or shrunk - but not actually ascii.

I''ll have a go at ripping all the useless bound checks out, and
see how painful it gets.

Hin-Tak

------------------------------
On Sun, Apr 13, 2014 12:01 AM BST Anton Altaparmakov wrote:

>Hi Hin-Tak,
>
>I think you are taking a sub-optimal approach!  Think about it: you are now performing the hfsplus_asc2uni() twice for each name being handled!  Once to check if the length is ok and once to get the actual result.  This is a waste of time.
>
>Instead, just do the conversion.  If the name is longer than allowed, hfsplus_asc2uni() will return -ENAMETOOLONG and at that point you can bail out.  There is no need to do a "test conversion" first the result of which you through away (and even worse you do a kmalloc() twice - once for the "test" and once for the real thing)...
>
>In fact you do it correctly in your proposed patch in hfsplus_attr_build_key(): You thrown out the length check and replace it with a call to hfsplus_asc2uni() that returns -ENAMETOOLONG if the name is too long and thus hfsplus_attr_build_key() returns -ENAMETOOLONG.  All you need to do is change the code to do the Right Thing when it gets back -ENAMETOOLONG and you are done (and you throw away all the bogus length checks in the upper layers).
>
>If you definitely want to do checking in advance, then that is fine, too - but don't do it with a test conversion - instead, convert it, check the length of the converted string and then use the converted name from there onwards.
>
>Both my suggestions are perhaps more involved changes than what you are doing but I think they are much more worthwhile as they do not introduce double the allocations and conversions.
>
>Best regards,
>
>    Anton
>
>On 12 Apr 2014, at 04:26, Hin-Tak Leung <hintak.leung@xxxxxxxxx> wrote:
>
>> From: Hin-Tak Leung <htl10@xxxxxxxxxxxxxxxxxxxxx>
>> 
>> HFSPLUS_ATTR_MAX_STRLEN (=127) is a limit for the number of unicode character
>> (UTF-16BE) storable in the HFS+ file system. Almost all the current
>> usage of it is wrong in relation to NLS to on-disk conversion.
>> 
>> Except for one use calling hfsplus_asc2uni (which should stay the same) and
>> its uses in calling hfsplus_uni2asc (which was changed in an earlier patch),
>> all the other uses are of the forms:
>> 
>> - char buffer[size]
>> 
>> - bound check: "if (input_length > size) return failure;"
>> 
>> Conversion between on-disk and NLS char strings (in whichever direction)
>> always needs to be in the worst, so all char buffers of that size
>> need to have a NLS_MAX_CHARSET_SIZE x .
>> 
>> The bound checks are all wrong, since they all compare
>> nls_length to unicode_length_limit.
>> 
>> A new function, hfsplus_try_asc2uni(), is introduced to
>> try the conversion, to do the bound-check instead. (After review this
>> will be splitted off as a separate earlier patch).
>> 
>> Before this patch, trying to set a 55 CJK character (in a UTF-8 locale)
>> + user prefix fails with:
>> 
>>    $ setfattr -n user.`cat testing-string` -v `cat testing-string` testing-string
>>    setfattr: testing-string: Operation not supported
>> 
>> and getting long attributes is particular ugly(!):
>> 
>>    find /mnt/* -type f -exec getfattr -d {} \;
>>    getfattr: /mnt/testing-string: Input/output error
>> 
>> with console log:
>>    [268008.389781] hfsplus: unicode conversion failed
>> 
>> After the patch, both of the above works.
>> 
>> However, I was not able to set double the size (110 + 5 is still under 127):
>> 
>>    $setfattr -n user.`cat testing-string testing-string` -v `cat testing-string testing-string` testing-string
>>    setfattr: testing-string: Numerical result out of range
>> 
>> But this also fails on ext2, so this failure is not HFS+ specific. It seems
>> that either the command line or the system call itself has a 256-byte limit.
>> (110 CJK char in UTF-8 is 330 bytes).
>> 
>> Signed-off-by: Hin-Tak Leung <htl10@xxxxxxxxxxxxxxxxxxxxx>
>> ---
>> fs/hfsplus/attributes.c     | 11 ++++-----
>> fs/hfsplus/hfsplus_fs.h     |  7 ++++++
>> fs/hfsplus/unicode.c        | 18 +++++++++++++++
>> fs/hfsplus/xattr.c          | 40 ++++++++++++++++++++++----------
>> fs/hfsplus/xattr_security.c | 56 ++++++++++++++++++++++++++++++---------------
>> fs/hfsplus/xattr_trusted.c  | 36 +++++++++++++++++++++--------
>> fs/hfsplus/xattr_user.c     | 36 +++++++++++++++++++++--------
>> 7 files changed, 147 insertions(+), 57 deletions(-)
>> 
>> diff --git a/fs/hfsplus/attributes.c b/fs/hfsplus/attributes.c
>> index caf89a7..f3345c0 100644
>> --- a/fs/hfsplus/attributes.c
>> +++ b/fs/hfsplus/attributes.c
>> @@ -54,14 +54,11 @@ int hfsplus_attr_build_key(struct super_block *sb, hfsplus_btree_key *key,
>>     memset(key, 0, sizeof(struct hfsplus_attr_key));
>>     key->attr.cnid = cpu_to_be32(cnid);
>>     if (name) {
>> -        len = strlen(name);
>> -        if (len > HFSPLUS_ATTR_MAX_STRLEN) {
>> -            pr_err("invalid xattr name's length\n");
>> -            return -EINVAL;
>> -        }
>> -        hfsplus_asc2uni(sb,
>> +        int res = hfsplus_asc2uni(sb,
>>                 (struct hfsplus_unistr *)&key->attr.key_name,
>> -                HFSPLUS_ATTR_MAX_STRLEN, name, len);
>> +                HFSPLUS_ATTR_MAX_STRLEN, name, strlen(name));
>> +        if (res)
>> +            return res;
>>         len = be16_to_cpu(key->attr.key_name.length);
>>     } else {
>>         key->attr.key_name.length = 0;
>> diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
>> index 83dc292..80257d0 100644
>> --- a/fs/hfsplus/hfsplus_fs.h
>> +++ b/fs/hfsplus/hfsplus_fs.h
>> @@ -507,6 +507,13 @@ int hfsplus_uni2asc(struct super_block *,
>>         const struct hfsplus_unistr *, char *, int *);
>> int hfsplus_asc2uni(struct super_block *,
>>         struct hfsplus_unistr *, int, const char *, int);
>> +int hfsplus_try_asc2uni_sb(struct super_block *sb,
>> +        const char *nls_name, int unilimit);
>> +static inline int hfsplus_try_asc2uni(const struct dentry *dentry,
>> +        const char *nls_name, int unilimit)
>> +{
>> +    return hfsplus_try_asc2uni_sb(dentry->d_sb, nls_name, unilimit);
>> +}
>> int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str);
>> int hfsplus_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
>>         unsigned int len, const char *str, const struct qstr *name);
>> diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
>> index e8ef121..cd00bd2 100644
>> --- a/fs/hfsplus/unicode.c
>> +++ b/fs/hfsplus/unicode.c
>> @@ -330,6 +330,24 @@ int hfsplus_asc2uni(struct super_block *sb,
>> }
>> 
>> /*
>> + * Try encoding an nls_name within a unicode size limit,
>> + * and see whether it will fit.
>> + */
>> +int hfsplus_try_asc2uni_sb(struct super_block *sb,
>> +            const char *nls_name, int unilimit)
>> +{
>> +    int res = 0;
>> +    struct hfsplus_unistr *ustr = kmalloc(sizeof(*ustr), GFP_KERNEL);
>> +    if (!ustr)
>> +        return -ENOMEM;
>> +
>> +    res = hfsplus_asc2uni(sb,
>> +        ustr, unilimit, nls_name, strlen(nls_name));
>> +    kfree(ustr);
>> +    return res;
>> +}
>> +
>> +/*
>>  * Hash a string to an integer as appropriate for the HFS+ filesystem.
>>  * Composed unicode characters are decomposed and case-folding is performed
>>  * if the appropriate bits are (un)set on the superblock.
>> diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
>> index 40c0a63..a05cab9 100644
>> --- a/fs/hfsplus/xattr.c
>> +++ b/fs/hfsplus/xattr.c
>> @@ -805,15 +805,15 @@ end_removexattr:
>> static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
>>                     void *buffer, size_t size, int type)
>> {
>> -    char xattr_name[HFSPLUS_ATTR_MAX_STRLEN +
>> -                XATTR_MAC_OSX_PREFIX_LEN + 1] = {0};
>> -    size_t len = strlen(name);
>> +    char *xattr_name;
>> +    int res;
>> 
>>     if (!strcmp(name, "))
>>         return -EINVAL;
>> 
>> -    if (len > HFSPLUS_ATTR_MAX_STRLEN)
>> -        return -EOPNOTSUPP;
>> +    res = hfsplus_try_asc2uni(dentry, name, HFSPLUS_ATTR_MAX_STRLEN);
>> +    if (res)
>> +        return res;
>> 
>>     /*
>>      * Don't allow retrieving properly prefixed attributes
>> @@ -821,22 +821,30 @@ static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
>>      */
>>     if (is_known_namespace(name))
>>         return -EOPNOTSUPP;
>> +    xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN
>> +        + XATTR_MAC_OSX_PREFIX_LEN + 1, GFP_KERNEL);
>> +    if (!xattr_name)
>> +        return -ENOMEM;
>> +    strcpy(xattr_name, XATTR_MAC_OSX_PREFIX);
>> +    strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name);
>> 
>> -    return hfsplus_getxattr(dentry, xattr_name, buffer, size);
>> +    res = hfsplus_getxattr(dentry, xattr_name, buffer, size);
>> +    kfree(xattr_name);
>> +    return res;
>> }
>> 
>> static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
>>         const void *buffer, size_t size, int flags, int type)
>> {
>> -    char xattr_name[HFSPLUS_ATTR_MAX_STRLEN +
>> -                XATTR_MAC_OSX_PREFIX_LEN + 1] = {0};
>> -    size_t len = strlen(name);
>> +    char *xattr_name;
>> +    int res;
>> 
>>     if (!strcmp(name, "))
>>         return -EINVAL;
>> 
>> -    if (len > HFSPLUS_ATTR_MAX_STRLEN)
>> -        return -EOPNOTSUPP;
>> +    res = hfsplus_try_asc2uni(dentry, name, HFSPLUS_ATTR_MAX_STRLEN);
>> +    if (res)
>> +        return res;
>> 
>>     /*
>>      * Don't allow setting properly prefixed attributes
>> @@ -844,8 +852,16 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
>>      */
>>     if (is_known_namespace(name))
>>         return -EOPNOTSUPP;
>> +    xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN
>> +        + XATTR_MAC_OSX_PREFIX_LEN + 1, GFP_KERNEL);
>> +    if (!xattr_name)
>> +        return -ENOMEM;
>> +    strcpy(xattr_name, XATTR_MAC_OSX_PREFIX);
>> +    strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name);
>> 
>> -    return hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
>> +    res = hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
>> +    kfree(xattr_name);
>> +    return res;
>> }
>> 
>> static size_t hfsplus_osx_listxattr(struct dentry *dentry, char *list,
>> diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c
>> index 0072276..f4993e0 100644
>> --- a/fs/hfsplus/xattr_security.c
>> +++ b/fs/hfsplus/xattr_security.c
>> @@ -14,37 +14,53 @@
>> static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
>>                     void *buffer, size_t size, int type)
>> {
>> -    char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
>> -    size_t len = strlen(name);
>> +    char *xattr_name;
>> +    int res;
>> 
>>     if (!strcmp(name, "))
>>         return -EINVAL;
>> 
>> -    if (len + XATTR_SECURITY_PREFIX_LEN > HFSPLUS_ATTR_MAX_STRLEN)
>> -        return -EOPNOTSUPP;
>> +    res = hfsplus_try_asc2uni(dentry, name,
>> +        HFSPLUS_ATTR_MAX_STRLEN - XATTR_SECURITY_PREFIX_LEN);
>> +    if (res)
>> +        return res;
>> 
>> +    xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
>> +        GFP_KERNEL);
>> +    if (!xattr_name)
>> +        return -ENOMEM;
>>     strcpy(xattr_name, XATTR_SECURITY_PREFIX);
>>     strcpy(xattr_name + XATTR_SECURITY_PREFIX_LEN, name);
>> 
>> -    return hfsplus_getxattr(dentry, xattr_name, buffer, size);
>> +    res = hfsplus_getxattr(dentry, xattr_name, buffer, size);
>> +    kfree(xattr_name);
>> +    return res;
>> }
>> 
>> static int hfsplus_security_setxattr(struct dentry *dentry, const char *name,
>>         const void *buffer, size_t size, int flags, int type)
>> {
>> -    char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
>> -    size_t len = strlen(name);
>> +    char *xattr_name;
>> +    int res;
>> 
>>     if (!strcmp(name, "))
>>         return -EINVAL;
>> 
>> -    if (len + XATTR_SECURITY_PREFIX_LEN > HFSPLUS_ATTR_MAX_STRLEN)
>> -        return -EOPNOTSUPP;
>> +    res = hfsplus_try_asc2uni(dentry, name,
>> +        HFSPLUS_ATTR_MAX_STRLEN - XATTR_SECURITY_PREFIX_LEN);
>> +    if (res)
>> +        return res;
>> 
>> +    xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
>> +        GFP_KERNEL);
>> +    if (!xattr_name)
>> +        return -ENOMEM;
>>     strcpy(xattr_name, XATTR_SECURITY_PREFIX);
>>     strcpy(xattr_name + XATTR_SECURITY_PREFIX_LEN, name);
>> 
>> -    return hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
>> +    res = hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
>> +    kfree(xattr_name);
>> +    return res;
>> }
>> 
>> static size_t hfsplus_security_listxattr(struct dentry *dentry, char *list,
>> @@ -62,31 +78,35 @@ static int hfsplus_initxattrs(struct inode *inode,
>>                 void *fs_info)
>> {
>>     const struct xattr *xattr;
>> -    char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
>> -    size_t xattr_name_len;
>> +    char *xattr_name;
>>     int err = 0;
>> 
>> +    xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
>> +        GFP_KERNEL);
>> +    if (!xattr_name)
>> +        return -ENOMEM;
>>     for (xattr = xattr_array; xattr->name != NULL; xattr++) {
>> -        xattr_name_len = strlen(xattr->name);
>> 
>> -        if (xattr_name_len == 0)
>> +        if (!strcmp(xattr->name, "))
>>             continue;
>> 
>> -        if (xattr_name_len + XATTR_SECURITY_PREFIX_LEN >
>> -                HFSPLUS_ATTR_MAX_STRLEN)
>> -            return -EOPNOTSUPP;
>> +        err = hfsplus_try_asc2uni_sb(inode->i_sb, xattr->name,
>> +            HFSPLUS_ATTR_MAX_STRLEN - XATTR_SECURITY_PREFIX_LEN);
>> +        if (err)
>> +            break;
>> 
>>         strcpy(xattr_name, XATTR_SECURITY_PREFIX);
>>         strcpy(xattr_name +
>>             XATTR_SECURITY_PREFIX_LEN, xattr->name);
>>         memset(xattr_name +
>> -            XATTR_SECURITY_PREFIX_LEN + xattr_name_len, 0, 1);
>> +            XATTR_SECURITY_PREFIX_LEN + strlen(xattr->name), 0, 1);
>> 
>>         err = __hfsplus_setxattr(inode, xattr_name,
>>                     xattr->value, xattr->value_len, 0);
>>         if (err)
>>             break;
>>     }
>> +    kfree(xattr_name);
>>     return err;
>> }
>> 
>> diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c
>> index 426cee2..36716af 100644
>> --- a/fs/hfsplus/xattr_trusted.c
>> +++ b/fs/hfsplus/xattr_trusted.c
>> @@ -12,37 +12,53 @@
>> static int hfsplus_trusted_getxattr(struct dentry *dentry, const char *name,
>>                     void *buffer, size_t size, int type)
>> {
>> -    char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
>> -    size_t len = strlen(name);
>> +    char *xattr_name;
>> +    int res;
>> 
>>     if (!strcmp(name, "))
>>         return -EINVAL;
>> 
>> -    if (len + XATTR_TRUSTED_PREFIX_LEN > HFSPLUS_ATTR_MAX_STRLEN)
>> -        return -EOPNOTSUPP;
>> +    res = hfsplus_try_asc2uni(dentry, name,
>> +        HFSPLUS_ATTR_MAX_STRLEN - XATTR_TRUSTED_PREFIX_LEN);
>> +    if (res)
>> +        return res;
>> 
>> +    xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
>> +        GFP_KERNEL);
>> +    if (!xattr_name)
>> +        return -ENOMEM;
>>     strcpy(xattr_name, XATTR_TRUSTED_PREFIX);
>>     strcpy(xattr_name + XATTR_TRUSTED_PREFIX_LEN, name);
>> 
>> -    return hfsplus_getxattr(dentry, xattr_name, buffer, size);
>> +    res = hfsplus_getxattr(dentry, xattr_name, buffer, size);
>> +    kfree(xattr_name);
>> +    return res;
>> }
>> 
>> static int hfsplus_trusted_setxattr(struct dentry *dentry, const char *name,
>>         const void *buffer, size_t size, int flags, int type)
>> {
>> -    char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
>> -    size_t len = strlen(name);
>> +    char *xattr_name;
>> +    int res;
>> 
>>     if (!strcmp(name, "))
>>         return -EINVAL;
>> 
>> -    if (len + XATTR_TRUSTED_PREFIX_LEN > HFSPLUS_ATTR_MAX_STRLEN)
>> -        return -EOPNOTSUPP;
>> +    res = hfsplus_try_asc2uni(dentry, name,
>> +        HFSPLUS_ATTR_MAX_STRLEN - XATTR_TRUSTED_PREFIX_LEN);
>> +    if (res)
>> +        return res;
>> 
>> +    xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
>> +        GFP_KERNEL);
>> +    if (!xattr_name)
>> +        return -ENOMEM;
>>     strcpy(xattr_name, XATTR_TRUSTED_PREFIX);
>>     strcpy(xattr_name + XATTR_TRUSTED_PREFIX_LEN, name);
>> 
>> -    return hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
>> +    res = hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
>> +    kfree(xattr_name);
>> +    return res;
>> }
>> 
>> static size_t hfsplus_trusted_listxattr(struct dentry *dentry, char *list,
>> diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c
>> index e340165..26b832c 100644
>> --- a/fs/hfsplus/xattr_user.c
>> +++ b/fs/hfsplus/xattr_user.c
>> @@ -12,37 +12,53 @@
>> static int hfsplus_user_getxattr(struct dentry *dentry, const char *name,
>>                     void *buffer, size_t size, int type)
>> {
>> -    char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
>> -    size_t len = strlen(name);
>> +    char *xattr_name;
>> +    int res;
>> 
>>     if (!strcmp(name, "))
>>         return -EINVAL;
>> 
>> -    if (len + XATTR_USER_PREFIX_LEN > HFSPLUS_ATTR_MAX_STRLEN)
>> -        return -EOPNOTSUPP;
>> +    res = hfsplus_try_asc2uni(dentry, name,
>> +        HFSPLUS_ATTR_MAX_STRLEN - XATTR_USER_PREFIX_LEN);
>> +    if (res)
>> +        return res;
>> 
>> +    xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
>> +        GFP_KERNEL);
>> +    if (!xattr_name)
>> +        return -ENOMEM;
>>     strcpy(xattr_name, XATTR_USER_PREFIX);
>>     strcpy(xattr_name + XATTR_USER_PREFIX_LEN, name);
>> 
>> -    return hfsplus_getxattr(dentry, xattr_name, buffer, size);
>> +    res = hfsplus_getxattr(dentry, xattr_name, buffer, size);
>> +    kfree(xattr_name);
>> +    return res;
>> }
>> 
>> static int hfsplus_user_setxattr(struct dentry *dentry, const char *name,
>>         const void *buffer, size_t size, int flags, int type)
>> {
>> -    char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
>> -    size_t len = strlen(name);
>> +    char *xattr_name;
>> +    int res;
>> 
>>     if (!strcmp(name, "))
>>         return -EINVAL;
>> 
>> -    if (len + XATTR_USER_PREFIX_LEN > HFSPLUS_ATTR_MAX_STRLEN)
>> -        return -EOPNOTSUPP;
>> +    res = hfsplus_try_asc2uni(dentry, name,
>> +        HFSPLUS_ATTR_MAX_STRLEN - XATTR_USER_PREFIX_LEN);
>> +    if (res)
>> +        return res;
>> 
>> +    xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
>> +        GFP_KERNEL);
>> +    if (!xattr_name)
>> +        return -ENOMEM;
>>     strcpy(xattr_name, XATTR_USER_PREFIX);
>>     strcpy(xattr_name + XATTR_USER_PREFIX_LEN, name);
>> 
>> -    return hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
>> +    res = hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
>> +    kfree(xattr_name);
>> +    return res;
>> }
>> 
>> static size_t hfsplus_user_listxattr(struct dentry *dentry, char *list,
>> -- 
>> 1.9.0
>> 
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>Best regards,
>
>    Anton
>-- 
>Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
>Unix Support, Computing Service, University of Cambridge
>J.J. Thomson Avenue, Cambridge, CB3 0RB, UK
>

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




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux