Fork me on GitHub

root/kernel/syscalls.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. free_name
  2. malloc_name
  3. check_user_permission
  4. check_group
  5. check_user_area
  6. check_permission
  7. do_bad_syscall
  8. do_syscall

   1 /*
   2  * fiwix/kernel/syscalls.c
   3  *
   4  * Copyright 2018, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/types.h>
   9 #include <fiwix/syscalls.h>
  10 #include <fiwix/mm.h>
  11 #include <fiwix/errno.h>
  12 #include <fiwix/string.h>
  13 
  14 #ifdef __DEBUG__
  15 #include <fiwix/stdio.h>
  16 #endif /*__DEBUG__ */
  17 
  18 void free_name(const char *name)
  19 {
  20         kfree((unsigned int)name);
  21 }
  22 
  23 /*
  24  * This function has two objectives:
  25  * 1. to check the memory address validity of the char pointer supplied by the
  26  *    user, while at the same time limit its length to PAGE_SIZE (4096) bytes.
  27  * 2. to create a copy of 'filename' in the kernel data space before using it.
  28  */
  29 int malloc_name(const char *filename, char **name)
  30 {
  31         struct vma *vma;
  32         unsigned int start;
  33         short int n, len;
  34         char *b;
  35 
  36         /*
  37          * Verifies if the 'vma' array of that process is not empty. It can
  38          * only be empty during the initialization of INIT, when it calls to
  39          * sys_execve and sys_open without having yet a proper setup.
  40          */
  41         if(current->vma[0].s_type != 0) {
  42                 if(!filename) {
  43                         return -EFAULT;
  44                 }
  45                 start = (unsigned int)filename;
  46                 if(!(vma = find_vma_region(start))) {
  47                         return -EFAULT;
  48                 }
  49                 if(!(vma->prot & PROT_READ)) {
  50                         return -EFAULT;
  51                 }
  52                 len = MIN(vma->end - start, PAGE_SIZE);
  53                 if(len < PAGE_SIZE) {
  54                         if((vma = find_vma_region(vma->end))) {
  55                                 if(vma->prot & PROT_READ) {
  56                                         len = PAGE_SIZE;
  57                                 }
  58                         }
  59                 }
  60         } else {
  61                 len = PAGE_SIZE;
  62         }
  63         if(!(b = (char *)kmalloc())) {
  64                 return -ENOMEM;
  65         }
  66         *name = b;
  67         for(n = 0; n < len; n++) {
  68                 if(!(*b = *filename)) {
  69                         return 0;
  70                 }
  71                 b++;
  72                 filename++;
  73         }
  74 
  75         free_name(*name);
  76         return -ENAMETOOLONG;
  77 }
  78 
  79 int check_user_permission(struct inode *i)
  80 {
  81         if(!IS_SUPERUSER) {
  82                 if(current->euid != i->i_uid) {
  83                         return 1;
  84                 }
  85         }
  86         return 0;
  87 }
  88 
  89 int check_group(struct inode *i)
  90 {
  91         int n;
  92         __gid_t gid;
  93 
  94         if(current->flags & PF_USEREAL) {
  95                 gid = current->gid;
  96         } else {
  97                 gid = current->egid;
  98         }
  99 
 100         if(i->i_gid == gid) {
 101                 return 0;
 102         }
 103 
 104         for(n = 0; n < NGROUPS_MAX; n++) {
 105                 if(current->groups[n] == -1) {
 106                         break;
 107                 }
 108                 if(current->groups[n] == i->i_gid) {
 109                         return 0;
 110                 }
 111         }
 112         return 1;
 113 }
 114 
 115 int check_user_area(int type, const void *addr, unsigned int size)
 116 {
 117         struct vma *vma;
 118         unsigned int start;
 119 
 120         /*
 121          * Verifies if the 'vma' array of that process is not empty. It can
 122          * only be empty during the initialization of INIT, when it calls to
 123          * sys_execve and sys_open without having yet a proper setup.
 124          */
 125         if(current->vma[0].s_type != 0) {
 126                 start = (unsigned int)addr;
 127                 if(!(vma = find_vma_region(start))) {
 128                         return -EFAULT;
 129                 }
 130 
 131                 for(;;) {
 132                         if(type == VERIFY_WRITE) {
 133                                 if(!(vma->prot & PROT_WRITE)) {
 134                                         return -EFAULT;
 135                                 }
 136                         } else {
 137                                 if(!(vma->prot & PROT_READ)) {
 138                                         return -EFAULT;
 139                                 }
 140                         }
 141                         if(start + size <= vma->end) {
 142                                 break;
 143                         }
 144                         if(!(vma = find_vma_region(vma->end))) {
 145                                 return -EFAULT;
 146                         }
 147                 }
 148         }
 149 
 150         return 0;
 151 }
 152 
 153 int check_permission(int mask, struct inode *i)
 154 {
 155         __uid_t uid;
 156 
 157         if(current->flags & PF_USEREAL) {
 158                 uid = current->uid;
 159         } else {
 160                 uid = current->euid;
 161         }
 162 
 163         if(uid == 0) {
 164                 return 0;
 165         }
 166         if(i->i_uid == uid) {
 167                 if((((i->i_mode >> 6) & 7) & mask) == mask) {
 168                         return 0;
 169                 }
 170         }
 171         if(!check_group(i)) {
 172                 if((((i->i_mode >> 3) & 7) & mask) == mask) {
 173                         return 0;
 174                 }
 175         }
 176         if(((i->i_mode & 7) & mask) == mask) {
 177                 return 0;
 178         }
 179 
 180         return -EACCES;
 181 }
 182 
 183 /* Linux 2.0.40 ABI system call (some from 2.2.26) */
 184 void *syscall_table[] = {
 185         NULL,                           /* 0 */ /* sys_setup (-ENOSYS) */
 186         sys_exit,
 187         sys_fork,
 188         sys_read,
 189         sys_write,
 190         sys_open,                       /* 5 */
 191         sys_close,
 192         sys_waitpid,
 193         sys_creat,
 194         sys_link,
 195         sys_unlink,                     /* 10 */
 196         sys_execve,
 197         sys_chdir,
 198         sys_time,
 199         sys_mknod,
 200         sys_chmod,                      /* 15 */
 201         sys_chown,
 202         NULL,                                   /* sys_break (-ENOSYS) */
 203         sys_stat,
 204         sys_lseek,
 205         sys_getpid,                     /* 20 */
 206         sys_mount,
 207         sys_umount,
 208         sys_setuid,
 209         sys_getuid,
 210         sys_stime,                      /* 25 */
 211         NULL,   // sys_ptrace
 212         sys_alarm,
 213         sys_fstat,
 214         sys_pause,
 215         sys_utime,                      /* 30 */
 216         NULL,                                   /* sys_stty (-ENOSYS) */
 217         NULL,                                   /* sys_gtty (-ENOSYS) */
 218         sys_access,
 219         NULL,   // sys_nice
 220         sys_ftime,                      /* 35 */
 221         sys_sync,
 222         sys_kill,
 223         sys_rename,
 224         sys_mkdir,
 225         sys_rmdir,                      /* 40 */
 226         sys_dup,
 227         sys_pipe,
 228         sys_times,
 229         NULL,   // sys_prof
 230         sys_brk,                        /* 45 */
 231         sys_setgid,
 232         sys_getgid,
 233         sys_signal,
 234         sys_geteuid,
 235         sys_getegid,                    /* 50 */
 236         NULL,   // sys_acct
 237         sys_umount2,
 238         NULL,                                   /* sys_lock (-ENOSYS) */
 239         sys_ioctl,
 240         sys_fcntl,                      /* 55 */
 241         NULL,                                   /* sys_mpx (-ENOSYS) */
 242         sys_setpgid,
 243         NULL,                                   /* sys_ulimit (-ENOSYS) */
 244         sys_olduname,
 245         sys_umask,                      /* 60 */
 246         sys_chroot,
 247         sys_ustat,
 248         sys_dup2,
 249         sys_getppid,
 250         sys_getpgrp,                    /* 65 */
 251         sys_setsid,
 252         sys_sigaction,
 253         sys_sgetmask,
 254         sys_ssetmask,
 255         sys_setreuid,                   /* 70 */
 256         sys_setregid,
 257         sys_sigsuspend,
 258         sys_sigpending,
 259         sys_sethostname,
 260         sys_setrlimit,                  /* 75 */
 261         sys_getrlimit,
 262         sys_getrusage,
 263         sys_gettimeofday,
 264         sys_settimeofday,
 265         sys_getgroups,                  /* 80 */
 266         sys_setgroups,
 267         old_select,
 268         sys_symlink,
 269         sys_lstat,
 270         sys_readlink,                   /* 85 */
 271         NULL,   // sys_uselib
 272         NULL,   // sys_swapon
 273         sys_reboot,
 274         NULL,   // old_readdir
 275         old_mmap,                       /* 90 */
 276         sys_munmap,
 277         sys_truncate,
 278         sys_ftruncate,
 279         sys_fchmod,
 280         sys_fchown,                     /* 95 */
 281         NULL,   // sys_getpriority
 282         NULL,   // sys_setpriority
 283         NULL,                                   /* sys_profil (-ENOSYS) */
 284         sys_statfs,
 285         sys_fstatfs,                    /* 100 */
 286         sys_ioperm,
 287         sys_socketcall, // sys_socketcall XXX
 288         NULL,   // sys_syslog
 289         sys_setitimer,
 290         sys_getitimer,                  /* 105 */
 291         sys_newstat,
 292         sys_newlstat,
 293         sys_newfstat,
 294         sys_uname,
 295         sys_iopl,                       /* 110 */
 296         NULL,   // sys_vhangup
 297         NULL,                                   /* sys_idle (-ENOSYS) */
 298         NULL,   // sys_vm86old
 299         sys_wait4,
 300         NULL,   // sys_swapoff          /* 115 */
 301         sys_sysinfo,
 302         NULL,   // sys_ipc
 303         sys_fsync,
 304         sys_sigreturn,
 305         NULL,   // sys_clone            /* 120 */
 306         sys_setdomainname,
 307         sys_newuname,
 308         NULL,   // sys_modify_ldt
 309         NULL,   // sys_adjtimex
 310         sys_mprotect,                   /* 125 */
 311         sys_sigprocmask,
 312         NULL,   // sys_create_module
 313         NULL,   // sys_init_module
 314         NULL,   // sys_delete_module
 315         NULL,   // sys_get_kernel_syms  /* 130 */
 316         NULL,   // sys_quotactl
 317         sys_getpgid,
 318         sys_fchdir,
 319         NULL,   // sys_bdflush
 320         NULL,   // sys_sysfs            /* 135 */
 321         sys_personality,
 322         NULL,                                   /* afs_syscall (-ENOSYS) */
 323         sys_setfsuid,
 324         sys_setfsgid,
 325         sys_llseek,                     /* 140 */
 326         sys_getdents,
 327         sys_select,
 328         sys_flock,
 329         NULL,   // sys_msync
 330         NULL,   // sys_readv            /* 145 */
 331         NULL,   // sys_writev
 332         sys_getsid,
 333         sys_fdatasync,
 334         NULL,   // sys_sysctl
 335         NULL,   // sys_mlock            /* 150 */
 336         NULL,   // sys_munlock
 337         NULL,   // sys_mlockall
 338         NULL,   // sys_munlockall
 339         NULL,   // sys_sched_setparam
 340         NULL,   // sys_sched_getparam   /* 155 */
 341         NULL,   // sys_sched_setscheduler
 342         NULL,   // sys_sched_getscheduler
 343         NULL,   // sys_sched_yield
 344         NULL,   // sys_sched_get_priority_max
 345         NULL,   // sys_sched_get_priority_min   /* 160 */
 346         NULL,   // sys_sched_rr_get_interval
 347         sys_nanosleep,
 348         NULL,   // sys_mremap
 349 
 350         NULL,
 351         NULL,
 352         NULL,
 353         NULL,
 354         NULL,
 355         NULL,
 356         NULL,
 357         NULL,
 358         NULL,
 359         NULL,
 360         NULL,
 361         NULL,
 362         NULL,
 363         NULL,
 364         NULL,
 365         NULL,
 366         NULL,
 367         NULL,
 368         sys_chown,                      /* 182 */
 369         sys_getcwd,
 370         NULL,
 371         NULL,
 372         NULL,
 373         NULL,
 374         NULL,
 375         NULL,
 376         sys_fork,                       /* 190 (sys_vfork) */
 377 };
 378 
 379 static void do_bad_syscall(unsigned int num)
 380 {
 381 #ifdef __DEBUG__
 382         printk("***** (pid %d) system call %d not supported yet *****\n", current->pid, num);
 383 #endif /*__DEBUG__ */
 384 }
 385 
 386 /*
 387  * The argument 'struct sigcontext' is needed because there are some system
 388  * calls (such as sys_iopl and sys_fork) that need to get information from
 389  * certain registers (EFLAGS and ESP). The rest of system calls will ignore
 390  * such extra argument.
 391  */
 392 int do_syscall(unsigned int num, int arg1, int arg2, int arg3, int arg4, int arg5, struct sigcontext sc)
 393 {
 394         int (*sys_func)(int, ...);
 395 
 396         if(num > NR_SYSCALLS) {
 397                 do_bad_syscall(num);
 398                 return -ENOSYS;
 399         }
 400         sys_func = syscall_table[num];
 401         if(!sys_func) {
 402                 do_bad_syscall(num);
 403                 return -ENOSYS;
 404         }
 405         current->sp = (unsigned int)&sc;
 406         return sys_func(arg1, arg2, arg3, arg4, arg5, &sc);
 407 }

/* [previous][next][first][last][top][bottom][index][help] */