Add O_PATH support for flistxattr()

A continuation of commit 2825f10b7f61558c264231a536cf3affc0d84204.

Add O_PATH compatibility support for flistxattr(). This allows
a process to list out all the extended attributes associated with
O_PATH file descriptors.

Change-Id: Ie2285ac7ad2e4eac427ddba6c2d182d41b130f75
This commit is contained in:
Nick Kralevich 2015-06-06 11:23:26 -07:00
parent 966f84b11d
commit e1d0810cd7
10 changed files with 108 additions and 13 deletions

View File

@ -130,6 +130,7 @@ libc_bionic_ndk_src_files := \
bionic/fchmodat.cpp \ bionic/fchmodat.cpp \
bionic/ffs.cpp \ bionic/ffs.cpp \
bionic/fgetxattr.cpp \ bionic/fgetxattr.cpp \
bionic/flistxattr.cpp \
bionic/flockfile.cpp \ bionic/flockfile.cpp \
bionic/fpclassify.cpp \ bionic/fpclassify.cpp \
bionic/fsetxattr.cpp \ bionic/fsetxattr.cpp \

View File

@ -124,7 +124,7 @@ int fchown:fchown(int, uid_t, gid_t) arm64,mips,mips64,x86_64
void sync(void) all void sync(void) all
int ___fsetxattr:fsetxattr(int, const char*, const void*, size_t, int) all int ___fsetxattr:fsetxattr(int, const char*, const void*, size_t, int) all
ssize_t ___fgetxattr:fgetxattr(int, const char*, void*, size_t) all ssize_t ___fgetxattr:fgetxattr(int, const char*, void*, size_t) all
ssize_t flistxattr(int, char*, size_t) all ssize_t ___flistxattr:flistxattr(int, char*, size_t) all
int fremovexattr(int, const char*) all int fremovexattr(int, const char*) all
int __getdents64:getdents64(unsigned int, struct dirent*, unsigned int) arm,arm64,mips,mips64,x86,x86_64 int __getdents64:getdents64(unsigned int, struct dirent*, unsigned int) arm,arm64,mips,mips64,x86,x86_64

View File

@ -2,7 +2,7 @@
#include <private/bionic_asm.h> #include <private/bionic_asm.h>
ENTRY(flistxattr) ENTRY(___flistxattr)
mov ip, r7 mov ip, r7
ldr r7, =__NR_flistxattr ldr r7, =__NR_flistxattr
swi #0 swi #0
@ -11,4 +11,5 @@ ENTRY(flistxattr)
bxls lr bxls lr
neg r0, r0 neg r0, r0
b __set_errno_internal b __set_errno_internal
END(flistxattr) END(___flistxattr)
.hidden ___flistxattr

View File

@ -2,7 +2,7 @@
#include <private/bionic_asm.h> #include <private/bionic_asm.h>
ENTRY(flistxattr) ENTRY(___flistxattr)
mov x8, __NR_flistxattr mov x8, __NR_flistxattr
svc #0 svc #0
@ -11,4 +11,5 @@ ENTRY(flistxattr)
b.hi __set_errno_internal b.hi __set_errno_internal
ret ret
END(flistxattr) END(___flistxattr)
.hidden ___flistxattr

View File

@ -2,7 +2,7 @@
#include <private/bionic_asm.h> #include <private/bionic_asm.h>
ENTRY(flistxattr) ENTRY(___flistxattr)
.set noreorder .set noreorder
.cpload t9 .cpload t9
li v0, __NR_flistxattr li v0, __NR_flistxattr
@ -16,4 +16,5 @@ ENTRY(flistxattr)
j t9 j t9
nop nop
.set reorder .set reorder
END(flistxattr) END(___flistxattr)
.hidden ___flistxattr

View File

@ -2,7 +2,7 @@
#include <private/bionic_asm.h> #include <private/bionic_asm.h>
ENTRY(flistxattr) ENTRY(___flistxattr)
.set push .set push
.set noreorder .set noreorder
li v0, __NR_flistxattr li v0, __NR_flistxattr
@ -22,4 +22,5 @@ ENTRY(flistxattr)
j t9 j t9
move ra, t0 move ra, t0
.set pop .set pop
END(flistxattr) END(___flistxattr)
.hidden ___flistxattr

View File

@ -2,7 +2,7 @@
#include <private/bionic_asm.h> #include <private/bionic_asm.h>
ENTRY(flistxattr) ENTRY(___flistxattr)
pushl %ebx pushl %ebx
.cfi_def_cfa_offset 8 .cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0 .cfi_rel_offset ebx, 0
@ -28,4 +28,5 @@ ENTRY(flistxattr)
popl %ecx popl %ecx
popl %ebx popl %ebx
ret ret
END(flistxattr) END(___flistxattr)
.hidden ___flistxattr

View File

@ -2,7 +2,7 @@
#include <private/bionic_asm.h> #include <private/bionic_asm.h>
ENTRY(flistxattr) ENTRY(___flistxattr)
movl $__NR_flistxattr, %eax movl $__NR_flistxattr, %eax
syscall syscall
cmpq $-MAX_ERRNO, %rax cmpq $-MAX_ERRNO, %rax
@ -12,4 +12,5 @@ ENTRY(flistxattr)
call __set_errno_internal call __set_errno_internal
1: 1:
ret ret
END(flistxattr) END(___flistxattr)
.hidden ___flistxattr

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
extern "C" ssize_t ___flistxattr(int, char*, size_t);
ssize_t flistxattr(int fd, char *list, size_t size) {
int saved_errno = errno;
ssize_t result = ___flistxattr(fd, list, size);
if ((result != -1) || (errno != EBADF)) {
return result;
}
// fd could be an O_PATH file descriptor, and the kernel
// may not directly support fgetxattr() on such a file descriptor.
// Use /proc/self/fd instead to emulate this support.
int fd_flag = fcntl(fd, F_GETFL);
if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
errno = EBADF;
return -1;
}
char buf[40];
snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
errno = saved_errno;
return listxattr(buf, list, size);
}

View File

@ -80,6 +80,7 @@ TEST(sys_xattr, fsetxattr_with_opath) {
ASSERT_EQ(-1, res); ASSERT_EQ(-1, res);
ASSERT_EQ(EBADF, errno); ASSERT_EQ(EBADF, errno);
#endif #endif
close(fd);
} }
TEST(sys_xattr, fsetxattr_with_opath_toosmall) { TEST(sys_xattr, fsetxattr_with_opath_toosmall) {
@ -97,4 +98,32 @@ TEST(sys_xattr, fsetxattr_with_opath_toosmall) {
ASSERT_EQ(-1, res); ASSERT_EQ(-1, res);
ASSERT_EQ(EBADF, errno); ASSERT_EQ(EBADF, errno);
#endif #endif
close(fd);
}
TEST(sys_xattr, flistattr) {
TemporaryFile tf;
char buf[65536]; // 64kB is max possible xattr list size. See "man 7 xattr".
ASSERT_EQ(0, fsetxattr(tf.fd, "user.foo", "bar", 4, 0));
ssize_t result = flistxattr(tf.fd, buf, sizeof(buf));
ASSERT_TRUE(result >= 9);
ASSERT_TRUE(memmem(buf, sizeof(buf), "user.foo", 9) != NULL);
}
TEST(sys_xattr, flistattr_opath) {
TemporaryFile tf;
char buf[65536]; // 64kB is max possible xattr list size. See "man 7 xattr".
ASSERT_EQ(0, fsetxattr(tf.fd, "user.foo", "bar", 4, 0));
int fd = open(tf.filename, O_PATH);
ASSERT_NE(-1, fd);
ssize_t res = flistxattr(fd, buf, sizeof(buf));
#if defined(__BIONIC__)
ASSERT_TRUE(res >= 9);
ASSERT_TRUE(static_cast<size_t>(res) <= sizeof(buf));
ASSERT_TRUE(memmem(buf, res, "user.foo", 9) != NULL);
#else
ASSERT_EQ(-1, res);
ASSERT_EQ(EBADF, errno);
#endif
close(fd);
} }