diff options
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r-- | linux-user/syscall.c | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 6b73769c34..7735008d6a 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -70,6 +70,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #ifdef CONFIG_EPOLL #include <sys/epoll.h> #endif +#ifdef CONFIG_ATTR +#include <attr/xattr.h> +#endif #define termios host_termios #define winsize host_winsize @@ -796,6 +799,15 @@ abi_long do_brk(abi_ulong new_brk) MAP_ANON|MAP_PRIVATE, 0, 0)); if (mapped_addr == brk_page) { + /* Heap contents are initialized to zero, as for anonymous + * mapped pages. Technically the new pages are already + * initialized to zero since they *are* anonymous mapped + * pages, however we have to take care with the contents that + * come from the remaining part of the previous page: it may + * contains garbage data due to a previous heap usage (grown + * then shrunken). */ + memset(g2h(target_brk), 0, brk_page - target_brk); + target_brk = new_brk; brk_page = HOST_PAGE_ALIGN(target_brk); DEBUGF_BRK("%#010x (mapped_addr == brk_page)\n", target_brk); @@ -7632,22 +7644,67 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif break; #endif +#ifdef CONFIG_ATTR #ifdef TARGET_NR_setxattr - case TARGET_NR_setxattr: case TARGET_NR_lsetxattr: case TARGET_NR_fsetxattr: - case TARGET_NR_getxattr: case TARGET_NR_lgetxattr: case TARGET_NR_fgetxattr: case TARGET_NR_listxattr: case TARGET_NR_llistxattr: case TARGET_NR_flistxattr: - case TARGET_NR_removexattr: case TARGET_NR_lremovexattr: case TARGET_NR_fremovexattr: ret = -TARGET_EOPNOTSUPP; break; + case TARGET_NR_setxattr: + { + void *p, *n, *v; + p = lock_user_string(arg1); + n = lock_user_string(arg2); + v = lock_user(VERIFY_READ, arg3, arg4, 1); + if (p && n && v) { + ret = get_errno(setxattr(p, n, v, arg4, arg5)); + } else { + ret = -TARGET_EFAULT; + } + unlock_user(p, arg1, 0); + unlock_user(n, arg2, 0); + unlock_user(v, arg3, 0); + } + break; + case TARGET_NR_getxattr: + { + void *p, *n, *v; + p = lock_user_string(arg1); + n = lock_user_string(arg2); + v = lock_user(VERIFY_WRITE, arg3, arg4, 0); + if (p && n && v) { + ret = get_errno(getxattr(p, n, v, arg4)); + } else { + ret = -TARGET_EFAULT; + } + unlock_user(p, arg1, 0); + unlock_user(n, arg2, 0); + unlock_user(v, arg3, arg4); + } + break; + case TARGET_NR_removexattr: + { + void *p, *n; + p = lock_user_string(arg1); + n = lock_user_string(arg2); + if (p && n) { + ret = get_errno(removexattr(p, n)); + } else { + ret = -TARGET_EFAULT; + } + unlock_user(p, arg1, 0); + unlock_user(n, arg2, 0); + } + break; #endif +#endif /* CONFIG_ATTR */ #ifdef TARGET_NR_set_thread_area case TARGET_NR_set_thread_area: #if defined(TARGET_MIPS) |