Skip to content

listxattr() may return EFAULT #4150

@nedbass

Description

@nedbass

On a dataset with xattr=sa, storing xattr values with certain lengths causes the xattr data to be stored in a corrupted nvlist on disk. This makes the xattr data inaccessible as system calls such as listxattr() and lgetxattr() return EFAULT. I have traced the return code to the function nvs_xdr_nvpair(). The lengths in the script below were determined through experimentation and reproduce the problem reliably.

#!/bin/sh
randbase64()
{
        dd if=/dev/urandom bs=1 count=$1 2>/dev/null | openssl enc -a -A
}

file=$1
touch $file
setfattr -h -n user.1 -v `randbase64 5000` $file
setfattr -h -n user.2 -v `randbase64 20000` $file
setfattr -h -n user.3 -v `randbase64 20000` $file
setfattr -h -n user.4 -v `randbase64 6000` $file

echo 3 > /proc/sys/vm/drop_caches
strace -e trace=lgetxattr ls -l $file
strace -e trace=listxattr getfattr -m. -d $file

Here is output from an example run of the above script.

$ zfs create -o xattr=sa tank/f
$ ./efault_reproducer.sh /tank/f/z
lgetxattr("/tank/f/z", "security.selinux", 0xd93300, 255) = -1 EFAULT (Bad address)
ls: /tank/f/z: Bad address
-rw-r--r-- 1 root root 0 Dec 28 11:27 /tank/f/z
listxattr("/tank/f/z", (nil), 0)        = -1 EFAULT (Bad address)
getfattr: /tank/f/z: Bad address

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions