LCOV - code coverage report
Current view: top level - arch/x86/kernel - sys_ia32.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 87 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 36 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on
       4             :  *             sys_sparc32
       5             :  *
       6             :  * Copyright (C) 2000           VA Linux Co
       7             :  * Copyright (C) 2000           Don Dugger <n0ano@valinux.com>
       8             :  * Copyright (C) 1999           Arun Sharma <arun.sharma@intel.com>
       9             :  * Copyright (C) 1997,1998      Jakub Jelinek (jj@sunsite.mff.cuni.cz)
      10             :  * Copyright (C) 1997           David S. Miller (davem@caip.rutgers.edu)
      11             :  * Copyright (C) 2000           Hewlett-Packard Co.
      12             :  * Copyright (C) 2000           David Mosberger-Tang <davidm@hpl.hp.com>
      13             :  * Copyright (C) 2000,2001,2002 Andi Kleen, SuSE Labs (x86-64 port)
      14             :  *
      15             :  * These routines maintain argument size conversion between 32bit and 64bit
      16             :  * environment. In 2.5 most of this should be moved to a generic directory.
      17             :  *
      18             :  * This file assumes that there is a hole at the end of user address space.
      19             :  *
      20             :  * Some of the functions are LE specific currently. These are
      21             :  * hopefully all marked.  This should be fixed.
      22             :  */
      23             : 
      24             : #include <linux/kernel.h>
      25             : #include <linux/sched.h>
      26             : #include <linux/fs.h>
      27             : #include <linux/file.h>
      28             : #include <linux/signal.h>
      29             : #include <linux/syscalls.h>
      30             : #include <linux/times.h>
      31             : #include <linux/utsname.h>
      32             : #include <linux/mm.h>
      33             : #include <linux/uio.h>
      34             : #include <linux/poll.h>
      35             : #include <linux/personality.h>
      36             : #include <linux/stat.h>
      37             : #include <linux/rwsem.h>
      38             : #include <linux/compat.h>
      39             : #include <linux/vfs.h>
      40             : #include <linux/ptrace.h>
      41             : #include <linux/highuid.h>
      42             : #include <linux/sysctl.h>
      43             : #include <linux/slab.h>
      44             : #include <linux/sched/task.h>
      45             : #include <asm/mman.h>
      46             : #include <asm/types.h>
      47             : #include <linux/uaccess.h>
      48             : #include <linux/atomic.h>
      49             : #include <asm/vgtod.h>
      50             : #include <asm/ia32.h>
      51             : 
      52             : #define AA(__x)         ((unsigned long)(__x))
      53             : 
      54           0 : SYSCALL_DEFINE3(ia32_truncate64, const char __user *, filename,
      55             :                 unsigned long, offset_low, unsigned long, offset_high)
      56             : {
      57           0 :         return ksys_truncate(filename,
      58           0 :                             ((loff_t) offset_high << 32) | offset_low);
      59             : }
      60             : 
      61           0 : SYSCALL_DEFINE3(ia32_ftruncate64, unsigned int, fd,
      62             :                 unsigned long, offset_low, unsigned long, offset_high)
      63             : {
      64           0 :         return ksys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low);
      65             : }
      66             : 
      67             : /* warning: next two assume little endian */
      68           0 : SYSCALL_DEFINE5(ia32_pread64, unsigned int, fd, char __user *, ubuf,
      69             :                 u32, count, u32, poslo, u32, poshi)
      70             : {
      71           0 :         return ksys_pread64(fd, ubuf, count,
      72           0 :                             ((loff_t)AA(poshi) << 32) | AA(poslo));
      73             : }
      74             : 
      75           0 : SYSCALL_DEFINE5(ia32_pwrite64, unsigned int, fd, const char __user *, ubuf,
      76             :                 u32, count, u32, poslo, u32, poshi)
      77             : {
      78           0 :         return ksys_pwrite64(fd, ubuf, count,
      79           0 :                              ((loff_t)AA(poshi) << 32) | AA(poslo));
      80             : }
      81             : 
      82             : 
      83             : /*
      84             :  * Some system calls that need sign extended arguments. This could be
      85             :  * done by a generic wrapper.
      86             :  */
      87           0 : SYSCALL_DEFINE6(ia32_fadvise64_64, int, fd, __u32, offset_low,
      88             :                 __u32, offset_high, __u32, len_low, __u32, len_high,
      89             :                 int, advice)
      90             : {
      91           0 :         return ksys_fadvise64_64(fd,
      92           0 :                                  (((u64)offset_high)<<32) | offset_low,
      93           0 :                                  (((u64)len_high)<<32) | len_low,
      94             :                                  advice);
      95             : }
      96             : 
      97           0 : SYSCALL_DEFINE4(ia32_readahead, int, fd, unsigned int, off_lo,
      98             :                 unsigned int, off_hi, size_t, count)
      99             : {
     100           0 :         return ksys_readahead(fd, ((u64)off_hi << 32) | off_lo, count);
     101             : }
     102             : 
     103           0 : SYSCALL_DEFINE6(ia32_sync_file_range, int, fd, unsigned int, off_low,
     104             :                 unsigned int, off_hi, unsigned int, n_low,
     105             :                 unsigned int, n_hi, int, flags)
     106             : {
     107           0 :         return ksys_sync_file_range(fd,
     108           0 :                                     ((u64)off_hi << 32) | off_low,
     109           0 :                                     ((u64)n_hi << 32) | n_low, flags);
     110             : }
     111             : 
     112           0 : SYSCALL_DEFINE5(ia32_fadvise64, int, fd, unsigned int, offset_lo,
     113             :                 unsigned int, offset_hi, size_t, len, int, advice)
     114             : {
     115           0 :         return ksys_fadvise64_64(fd, ((u64)offset_hi << 32) | offset_lo,
     116             :                                  len, advice);
     117             : }
     118             : 
     119           0 : SYSCALL_DEFINE6(ia32_fallocate, int, fd, int, mode,
     120             :                 unsigned int, offset_lo, unsigned int, offset_hi,
     121             :                 unsigned int, len_lo, unsigned int, len_hi)
     122             : {
     123           0 :         return ksys_fallocate(fd, mode, ((u64)offset_hi << 32) | offset_lo,
     124           0 :                               ((u64)len_hi << 32) | len_lo);
     125             : }
     126             : 
     127             : #ifdef CONFIG_IA32_EMULATION
     128             : /*
     129             :  * Another set for IA32/LFS -- x86_64 struct stat is different due to
     130             :  * support for 64bit inode numbers.
     131             :  */
     132           0 : static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat)
     133             : {
     134           0 :         typeof(ubuf->st_uid) uid = 0;
     135           0 :         typeof(ubuf->st_gid) gid = 0;
     136           0 :         SET_UID(uid, from_kuid_munged(current_user_ns(), stat->uid));
     137           0 :         SET_GID(gid, from_kgid_munged(current_user_ns(), stat->gid));
     138           0 :         if (!user_write_access_begin(ubuf, sizeof(struct stat64)))
     139             :                 return -EFAULT;
     140           0 :         unsafe_put_user(huge_encode_dev(stat->dev), &ubuf->st_dev, Efault);
     141           0 :         unsafe_put_user(stat->ino, &ubuf->__st_ino, Efault);
     142           0 :         unsafe_put_user(stat->ino, &ubuf->st_ino, Efault);
     143           0 :         unsafe_put_user(stat->mode, &ubuf->st_mode, Efault);
     144           0 :         unsafe_put_user(stat->nlink, &ubuf->st_nlink, Efault);
     145           0 :         unsafe_put_user(uid, &ubuf->st_uid, Efault);
     146           0 :         unsafe_put_user(gid, &ubuf->st_gid, Efault);
     147           0 :         unsafe_put_user(huge_encode_dev(stat->rdev), &ubuf->st_rdev, Efault);
     148           0 :         unsafe_put_user(stat->size, &ubuf->st_size, Efault);
     149           0 :         unsafe_put_user(stat->atime.tv_sec, &ubuf->st_atime, Efault);
     150           0 :         unsafe_put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec, Efault);
     151           0 :         unsafe_put_user(stat->mtime.tv_sec, &ubuf->st_mtime, Efault);
     152           0 :         unsafe_put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec, Efault);
     153           0 :         unsafe_put_user(stat->ctime.tv_sec, &ubuf->st_ctime, Efault);
     154           0 :         unsafe_put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec, Efault);
     155           0 :         unsafe_put_user(stat->blksize, &ubuf->st_blksize, Efault);
     156           0 :         unsafe_put_user(stat->blocks, &ubuf->st_blocks, Efault);
     157           0 :         user_access_end();
     158           0 :         return 0;
     159             : Efault:
     160             :         user_write_access_end();
     161             :         return -EFAULT;
     162             : }
     163             : 
     164           0 : COMPAT_SYSCALL_DEFINE2(ia32_stat64, const char __user *, filename,
     165             :                        struct stat64 __user *, statbuf)
     166             : {
     167           0 :         struct kstat stat;
     168           0 :         int ret = vfs_stat(filename, &stat);
     169             : 
     170           0 :         if (!ret)
     171           0 :                 ret = cp_stat64(statbuf, &stat);
     172           0 :         return ret;
     173             : }
     174             : 
     175           0 : COMPAT_SYSCALL_DEFINE2(ia32_lstat64, const char __user *, filename,
     176             :                        struct stat64 __user *, statbuf)
     177             : {
     178           0 :         struct kstat stat;
     179           0 :         int ret = vfs_lstat(filename, &stat);
     180           0 :         if (!ret)
     181           0 :                 ret = cp_stat64(statbuf, &stat);
     182           0 :         return ret;
     183             : }
     184             : 
     185           0 : COMPAT_SYSCALL_DEFINE2(ia32_fstat64, unsigned int, fd,
     186             :                        struct stat64 __user *, statbuf)
     187             : {
     188           0 :         struct kstat stat;
     189           0 :         int ret = vfs_fstat(fd, &stat);
     190           0 :         if (!ret)
     191           0 :                 ret = cp_stat64(statbuf, &stat);
     192           0 :         return ret;
     193             : }
     194             : 
     195           0 : COMPAT_SYSCALL_DEFINE4(ia32_fstatat64, unsigned int, dfd,
     196             :                        const char __user *, filename,
     197             :                        struct stat64 __user *, statbuf, int, flag)
     198             : {
     199           0 :         struct kstat stat;
     200           0 :         int error;
     201             : 
     202           0 :         error = vfs_fstatat(dfd, filename, &stat, flag);
     203           0 :         if (error)
     204           0 :                 return error;
     205           0 :         return cp_stat64(statbuf, &stat);
     206             : }
     207             : 
     208             : /*
     209             :  * Linux/i386 didn't use to be able to handle more than
     210             :  * 4 system call parameters, so these system calls used a memory
     211             :  * block for parameter passing..
     212             :  */
     213             : 
     214             : struct mmap_arg_struct32 {
     215             :         unsigned int addr;
     216             :         unsigned int len;
     217             :         unsigned int prot;
     218             :         unsigned int flags;
     219             :         unsigned int fd;
     220             :         unsigned int offset;
     221             : };
     222             : 
     223           0 : COMPAT_SYSCALL_DEFINE1(ia32_mmap, struct mmap_arg_struct32 __user *, arg)
     224             : {
     225           0 :         struct mmap_arg_struct32 a;
     226             : 
     227           0 :         if (copy_from_user(&a, arg, sizeof(a)))
     228             :                 return -EFAULT;
     229             : 
     230           0 :         if (a.offset & ~PAGE_MASK)
     231             :                 return -EINVAL;
     232             : 
     233           0 :         return ksys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
     234           0 :                                a.offset>>PAGE_SHIFT);
     235             : }
     236             : 
     237             : /*
     238             :  * The 32-bit clone ABI is CONFIG_CLONE_BACKWARDS
     239             :  */
     240           0 : COMPAT_SYSCALL_DEFINE5(ia32_clone, unsigned long, clone_flags,
     241             :                        unsigned long, newsp, int __user *, parent_tidptr,
     242             :                        unsigned long, tls_val, int __user *, child_tidptr)
     243             : {
     244           0 :         struct kernel_clone_args args = {
     245           0 :                 .flags          = (clone_flags & ~CSIGNAL),
     246             :                 .pidfd          = parent_tidptr,
     247             :                 .child_tid      = child_tidptr,
     248             :                 .parent_tid     = parent_tidptr,
     249           0 :                 .exit_signal    = (clone_flags & CSIGNAL),
     250             :                 .stack          = newsp,
     251             :                 .tls            = tls_val,
     252             :         };
     253             : 
     254           0 :         return kernel_clone(&args);
     255             : }
     256             : #endif /* CONFIG_IA32_EMULATION */

Generated by: LCOV version 1.14