diff --git a/compat/posix/src/misc.c b/compat/posix/src/misc.c index e740930f12e6a90809eea886f2baa46459f50695..39337571cc96dd021f5f966cba0f790d5745f05c 100644 --- a/compat/posix/src/misc.c +++ b/compat/posix/src/misc.c @@ -36,7 +36,7 @@ #include "sys/utsname.h" #include "mqueue.h" #include "semaphore.h" - +#include "los_hw.h" /* * Supply some suitable values for constants that may not be present @@ -52,17 +52,27 @@ int uname(struct utsname *name) { INT32 ret; + const char *cpuInfo = NULL; + if (name == NULL) { return -EFAULT; } (VOID)strncpy_s(name->sysname, sizeof(name->sysname), KERNEL_NAME, strlen(KERNEL_NAME) + 1); (VOID)strncpy_s(name->nodename, sizeof(name->nodename), "hisilicon", strlen("hisilicon") + 1); - ret = snprintf_s(name->version, sizeof(name->version), sizeof(name->version) - 1, "%s %u.%u.%u.%u %s %s\n", + ret = snprintf_s(name->version, sizeof(name->version), sizeof(name->version) - 1, "%s %u.%u.%u.%u %s %s", KERNEL_NAME, KERNEL_MAJOR, KERNEL_MINOR, KERNEL_PATCH, KERNEL_ITRE, __DATE__, __TIME__); if (ret < 0) { return -EIO; } - name->machine[0] = '\0'; + + cpuInfo = LOS_CpuInfo(); + (VOID)strncpy_s(name->machine, sizeof(name->machine), cpuInfo, sizeof(name->machine)); + ret = snprintf_s(name->release, sizeof(name->release), sizeof(name->release) - 1, "%u.%u.%u.%u", + KERNEL_MAJOR, KERNEL_MINOR, KERNEL_PATCH, KERNEL_ITRE); + if (ret < 0) { + return -EIO; + } + name->domainname[0] = '\0'; return 0; } diff --git a/syscall/fs_syscall.c b/syscall/fs_syscall.c index c4f0af49189a1e67f7e6e28f388834f665dbd0dd..676402a5d498e455904c9b7bcf0b04c5ce21b390 100644 --- a/syscall/fs_syscall.c +++ b/syscall/fs_syscall.c @@ -29,11 +29,13 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "syscall_pub.h" #ifdef LOSCFG_FS_VFS #include "errno.h" #include "unistd.h" #include "fs/fd_table.h" #include "fs/file.h" +#include "fs/fs.h" #include "fs/fs_operation.h" #include "sys/mount.h" #include "los_task_pri.h" @@ -56,29 +58,77 @@ #include "sys/statfs.h" #define HIGH_SHIFT_BIT 32 +#define TIMESPEC_TIMES_NUM 2 -static int UserPathCopy(const char *userPath, char **pathBuf) +static int CheckNewAttrTime(struct IATTR *attr, struct timespec times[TIMESPEC_TIMES_NUM]) { - int ret; + int ret = ENOERR; + struct timespec stp = {0}; - *pathBuf = (char *)LOS_MemAlloc(OS_SYS_MEM_ADDR, PATH_MAX + 1); - if (*pathBuf == NULL) { - return -ENOMEM; + if (times) { + if (times[0].tv_nsec == UTIME_OMIT) { + attr->attr_chg_valid &= ~CHG_ATIME; + } else if (times[0].tv_nsec == UTIME_NOW) { + ret = clock_gettime(CLOCK_REALTIME, &stp); + if (ret < 0) { + return -get_errno(); + } + attr->attr_chg_atime = (unsigned int)stp.tv_sec; + attr->attr_chg_valid |= CHG_ATIME; + } else { + attr->attr_chg_atime = (unsigned int)times[0].tv_sec; + attr->attr_chg_valid |= CHG_ATIME; + } + + if (times[1].tv_nsec == UTIME_OMIT) { + attr->attr_chg_valid &= ~CHG_MTIME; + } else if (times[1].tv_nsec == UTIME_NOW) { + ret = clock_gettime(CLOCK_REALTIME, &stp); + if (ret < 0) { + return -get_errno(); + } + attr->attr_chg_mtime = (unsigned int)stp.tv_sec; + attr->attr_chg_valid |= CHG_MTIME; + } else { + attr->attr_chg_mtime = (unsigned int)times[1].tv_sec; + attr->attr_chg_valid |= CHG_MTIME; + } + } else { + ret = clock_gettime(CLOCK_REALTIME, &stp); + if (ret < 0) { + return -get_errno(); + } + attr->attr_chg_atime = (unsigned int)stp.tv_sec; + attr->attr_chg_mtime = (unsigned int)stp.tv_sec; + attr->attr_chg_valid |= CHG_ATIME; + attr->attr_chg_valid |= CHG_MTIME; } - ret = LOS_StrncpyFromUser(*pathBuf, userPath, PATH_MAX + 1); - if (ret < 0) { - (void)LOS_MemFree(OS_SYS_MEM_ADDR, *pathBuf); - *pathBuf = NULL; - return ret; - } else if (ret > PATH_MAX) { - (void)LOS_MemFree(OS_SYS_MEM_ADDR, *pathBuf); - *pathBuf = NULL; - return -ENAMETOOLONG; + return ret; +} + +static int GetFullpathNull(int fd, const char *path, char **filePath) +{ + int ret; + char *fullPath = NULL; + struct file *file = NULL; + + if ((fd != AT_FDCWD) && (path == NULL)) { + fd = GetAssociatedSystemFd(fd); + ret = fs_getfilep(fd, &file); + if (ret < 0) { + return -get_errno(); + } + fullPath = file->f_path; + } else { + ret = GetFullpath(fd, path, &fullPath); + if (ret < 0) { + return ret; + } } - (*pathBuf)[ret] = '\0'; - return 0; + *filePath = fullPath; + return ret; } static int UserIovItemCheck(const struct iovec *iov, const int iovcnt) @@ -2124,6 +2174,37 @@ OUT: return result; } +int SysUtimensat(int fd, const char *path, struct timespec times[TIMESPEC_TIMES_NUM], int flag) +{ + int ret; + int timeLen; + struct IATTR attr = {0}; + char *filePath = NULL; + + timeLen = TIMESPEC_TIMES_NUM * sizeof(struct timespec); + CHECK_ASPACE(times, timeLen); + DUP_FROM_USER(times, timeLen); + ret = CheckNewAttrTime(&attr, times); + FREE_DUP(times); + if (ret < 0) { + goto OUT; + } + + ret = GetFullpathNull(fd, path, &filePath); + if (ret < 0) { + goto OUT; + } + + ret = chattr(filePath, &attr); + if (ret < 0) { + ret = -get_errno(); + } + +OUT: + PointerFree(filePath); + return ret; +} + int SysChmod(const char *pathname, mode_t mode) { int ret; @@ -2148,6 +2229,112 @@ OUT: return ret; } +int SysFchmodat(int fd, const char *path, mode_t mode, int flag) +{ + int ret; + char *pathRet = NULL; + char *fullpath = NULL; + struct IATTR attr = { + .attr_chg_mode = mode, + .attr_chg_valid = CHG_MODE, + }; + + if (path != NULL) { + ret = UserPathCopy(path, &pathRet); + if (ret != 0) { + goto OUT; + } + } + + if (fd != AT_FDCWD) { + /* Process fd convert to system global fd */ + fd = GetAssociatedSystemFd(fd); + } + + ret = vfs_normalize_pathat(fd, pathRet, &fullpath); + if (ret < 0) { + goto OUT; + } + + ret = chattr(fullpath, &attr); + if (ret < 0) { + ret = -get_errno(); + } + +OUT: + PointerFree(pathRet); + PointerFree(fullpath); + + return ret; +} + +int SysFchownat(int fd, const char *path, uid_t owner, gid_t group, int flag) +{ + int ret; + char *fullpath = NULL; + struct IATTR attr = { + .attr_chg_valid = 0, + }; + + ret = GetFullpath(fd, path, &fullpath); + if (ret < 0) { + goto OUT; + } + + if (owner != (uid_t)-1) { + attr.attr_chg_uid = owner; + attr.attr_chg_valid |= CHG_UID; + } + if (group != (gid_t)-1) { + attr.attr_chg_gid = group; + attr.attr_chg_valid |= CHG_GID; + } + + ret = chattr(fullpath, &attr); + if (ret < 0) { + ret = -get_errno(); + } + +OUT: + PointerFree(fullpath); + + return ret; +} + +int SysFchown(int fd, uid_t owner, gid_t group) +{ + int ret; + int sysFd; + struct IATTR attr = {0}; + attr.attr_chg_valid = 0; + struct file *file = NULL; + + sysFd = GetAssociatedSystemFd(fd); + if (sysFd < 0) { + return -EBADF; + } + + ret = fs_getfilep(sysFd, &file); + if (ret < 0) { + return -get_errno(); + } + + if (owner != (uid_t)-1) { + attr.attr_chg_uid = owner; + attr.attr_chg_valid |= CHG_UID; + } + if (group != (gid_t)-1) { + attr.attr_chg_gid = group; + attr.attr_chg_valid |= CHG_GID; + } + ret = chattr(file->f_path, &attr); + if (ret < 0) { + ret = -get_errno(); + } + + return ret; +} + int SysChown(const char *pathname, uid_t owner, gid_t group) { int ret; @@ -2218,4 +2405,43 @@ OUT: } return ret; } + +int SysFaccessat(int fd, const char *filename, int amode, int flag) +{ + int ret; + struct stat buf; + struct statfs fsBuf; + char *fullDirectory = NULL; + + ret = GetFullpath(fd, filename, &fullDirectory); + if (ret < 0) { + goto OUT; + } + + ret = statfs(fullDirectory, &fsBuf); + if (ret != 0) { + ret = -get_errno(); + goto OUT; + } + + if ((fsBuf.f_flags & MS_RDONLY) && ((unsigned int)amode & W_OK)) { + ret = -EROFS; + goto OUT; + } + + ret = stat(fullDirectory, &buf); + if (ret != 0) { + ret = -get_errno(); + goto OUT; + } + + if (VfsPermissionCheck(buf.st_uid, buf.st_gid, buf.st_mode, amode)) { + ret = -EACCES; + } + +OUT: + PointerFree(fullDirectory); + + return ret; +} #endif diff --git a/syscall/los_syscall.c b/syscall/los_syscall.c index b590c97a108bda972fbed4fdc143c26e8823013f..6761fff79413925ea5d3f3f544938e028e611e45 100644 --- a/syscall/los_syscall.c +++ b/syscall/los_syscall.c @@ -32,7 +32,6 @@ #define _GNU_SOURCE #ifdef LOSCFG_FS_VFS #include "fs/file.h" -#include "fs/file.h" #endif #include "los_init.h" #include "los_signal.h" diff --git a/syscall/los_syscall.h b/syscall/los_syscall.h index 1934673da6df2e5ba20f709b6f38322e128fe62e..f73346702f70947518245a0201ece3bb96e5e432 100644 --- a/syscall/los_syscall.h +++ b/syscall/los_syscall.h @@ -231,7 +231,11 @@ extern ssize_t SysReadlinkat(int dirfd, const char *pathname, char *buf, size_t extern int SysUnlink( const char *pathname); extern int SysExecve(const char *fileName, char *const *argv, char *const *envp); extern int SysChdir(const char *path); +extern int SysUtimensat(int fd, const char *path, struct timespec times[2], int flag); +extern int SysFchmodat(int fd, const char *path, mode_t mode, int flag); extern int SysChmod(const char *path, mode_t mode); +extern int SysFchownat(int fd, const char *path, uid_t owner, gid_t group, int flag); +extern int SysFchown(int fd, uid_t owner, gid_t group); extern int SysChown(const char *pathname, uid_t owner, gid_t group); extern off_t SysLseek(int fd, off_t offset, int whence); extern off64_t SysLseek64(int fd, int offsetHigh, int offsetLow, off64_t *result, int whence); @@ -239,6 +243,7 @@ extern int SysMount(const char *source, const char *target, const char *filesyst const void *data); extern int SysUmount(const char *target); extern int SysAccess(const char *path, int amode); +extern int SysFaccessat(int fd, const char *filename, int amode, int flag); extern int SysRename(const char *oldpath, const char *newpath); extern int SysMkdir(const char *pathname, mode_t mode); extern int SysRmdir(const char *pathname); diff --git a/syscall/syscall_lookup.h b/syscall/syscall_lookup.h index 236f7a25201925d6a45423ecc1803a92a5dbd654..4419073280bcb3e1526898c3e7f9097cec4178b2 100644 --- a/syscall/syscall_lookup.h +++ b/syscall/syscall_lookup.h @@ -48,11 +48,15 @@ SYSCALL_HAND_DEF(__NR_execve, SysExecve, int, ARG_NUM_3) SYSCALL_HAND_DEF(__NR_sysinfo, SysInfo, int, ARG_NUM_1) SYSCALL_HAND_DEF(__NR_chdir, SysChdir, int, ARG_NUM_1) +SYSCALL_HAND_DEF(__NR_utimensat, SysUtimensat, int, ARG_NUM_4) +SYSCALL_HAND_DEF(__NR_fchmodat, SysFchmodat, int, ARG_NUM_4) +SYSCALL_HAND_DEF(__NR_utimensat, SysUtimensat, int, ARG_NUM_4) SYSCALL_HAND_DEF(__NR_chmod, SysChmod, int, ARG_NUM_2) SYSCALL_HAND_DEF(__NR_lseek, SysLseek, off_t, ARG_NUM_7) /* current only support 32bit max 4G file */ SYSCALL_HAND_DEF(__NR_mount, SysMount, int, ARG_NUM_5) SYSCALL_HAND_DEF(__NR_umount, SysUmount, int, ARG_NUM_1) SYSCALL_HAND_DEF(__NR_access, SysAccess, int, ARG_NUM_2) +SYSCALL_HAND_DEF(__NR_faccessat, SysFaccessat, int, ARG_NUM_4) SYSCALL_HAND_DEF(__NR_sync, SysSync, void, ARG_NUM_0) SYSCALL_HAND_DEF(__NR_rename, SysRename, int, ARG_NUM_2) SYSCALL_HAND_DEF(__NR_mkdir, SysMkdir, int, ARG_NUM_2) @@ -166,6 +170,8 @@ SYSCALL_HAND_DEF(__NR_rt_sigpending, SysSigPending, int, ARG_NUM_1) SYSCALL_HAND_DEF(__NR_rt_sigtimedwait, SysSigTimedWait, int, ARG_NUM_4) SYSCALL_HAND_DEF(__NR_rt_sigsuspend, SysSigSuspend, int, ARG_NUM_1) +SYSCALL_HAND_DEF(__NR_fchownat, SysFchownat, int, ARG_NUM_5) +SYSCALL_HAND_DEF(__NR_fchown32, SysFchown, int, ARG_NUM_3) SYSCALL_HAND_DEF(__NR_chown, SysChown, int, ARG_NUM_3) SYSCALL_HAND_DEF(__NR_chown32, SysChown, int, ARG_NUM_3) #ifdef LOSCFG_SECURITY_CAPABILITY diff --git a/syscall/syscall_pub.c b/syscall/syscall_pub.c index dbfd0f5abe246e04e9e7926081d02f5686e60591..759b74a36cf698b427490ac6589fa67a81a0ff55 100644 --- a/syscall/syscall_pub.c +++ b/syscall/syscall_pub.c @@ -60,3 +60,68 @@ void *DupUserMem(const void *ptr, size_t len, int needCopy) return p; } + +int GetFullpath(int fd, const char *path, char **fullpath) +{ + int ret = 0; + char *pathRet = NULL; + struct file *file = NULL; + struct stat bufRet = {0}; + + if (path != NULL) { + ret = UserPathCopy(path, &pathRet); + if (ret != 0) { + goto OUT; + } + } + + if ((pathRet != NULL) && (*pathRet == '/')) { + *fullpath = pathRet; + pathRet = NULL; + } else { + if (fd != AT_FDCWD) { + /* Process fd convert to system global fd */ + fd = GetAssociatedSystemFd(fd); + } + ret = fs_getfilep(fd, &file); + if (file) { + ret = stat(file->f_path, &bufRet); + if (!ret) { + if (!S_ISDIR(bufRet.st_mode)) { + set_errno(ENOTDIR); + ret = -ENOTDIR; + goto OUT; + } + } + } + ret = vfs_normalize_pathat(fd, pathRet, fullpath); + } + +OUT: + PointerFree(pathRet); + return ret; +} + +int UserPathCopy(const char *userPath, char **pathBuf) +{ + int ret; + + *pathBuf = (char *)LOS_MemAlloc(OS_SYS_MEM_ADDR, PATH_MAX + 1); + if (*pathBuf == NULL) { + return -ENOMEM; + } + + ret = LOS_StrncpyFromUser(*pathBuf, userPath, PATH_MAX + 1); + if (ret < 0) { + (void)LOS_MemFree(OS_SYS_MEM_ADDR, *pathBuf); + *pathBuf = NULL; + return ret; + } else if (ret > PATH_MAX) { + (void)LOS_MemFree(OS_SYS_MEM_ADDR, *pathBuf); + *pathBuf = NULL; + return -ENAMETOOLONG; + } + (*pathBuf)[ret] = '\0'; + + return 0; +} diff --git a/syscall/syscall_pub.h b/syscall/syscall_pub.h index 5299398774feef82d59215476ce3809ed0f18b80..e784a51066ee85cbdf7e468c0ad3d7741e54980d 100644 --- a/syscall/syscall_pub.h +++ b/syscall/syscall_pub.h @@ -36,9 +36,14 @@ #include "los_vm_lock.h" #include "los_vm_map.h" #include "user_copy.h" +#include "fs/fs.h" +#include "fcntl.h" +#include "los_strncpy_from_user.h" extern int CheckRegion(const LosVmSpace *space, VADDR_T ptr, size_t len); extern void *DupUserMem(const void *ptr, size_t len, int needCopy); +extern int GetFullpath(int fd, const char *path, char **fullpath); +extern int UserPathCopy(const char *userPath, char **pathBuf); #define CHECK_ASPACE(ptr, len, ...) \ do { \