diff --git a/sys/dev/dev_dmem.pas b/sys/dev/dev_dmem.pas new file mode 100644 index 00000000..b9664253 --- /dev/null +++ b/sys/dev/dev_dmem.pas @@ -0,0 +1,82 @@ +unit dev_dmem; + +{$mode ObjFPC}{$H+} +{$CALLING SysV_ABI_CDecl} + +interface + +uses + kern_conf; + +procedure dmemdev_init(); + +implementation + +uses + errno, + vuio, + subr_uio, + vm, + kern_dmem; + +Const + SCE_KERNEL_MAIN_DMEM_SIZE=$180000000; //6GB + +Function dmem_ioctl(dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer; +begin + Result:=0; + + Writeln('dmem_ioctl("',dev^.si_name,'",0x',HexStr(cmd,8),',0x',HexStr(fflag,8),')'); + + case cmd of + $4008800A: //sceKernelGetDirectMemorySize + begin + PQWORD(data)^:=SCE_KERNEL_MAIN_DMEM_SIZE; + end; + else + Assert(False); + end; + +end; + +Function dmem_mmap(dev:p_cdev;offset:vm_ooffset_t;paddr:p_vm_paddr_t;nprot:Integer;memattr:p_vm_memattr_t):Integer; +begin + Result:=0; + + Writeln('dmem_mmap("',dev^.si_name,'",0x',HexStr(offset,8),',0x',HexStr(paddr),',',nprot,')'); + Assert(False); +end; + +const + dmem_cdevsw:t_cdevsw=( + d_version :D_VERSION; + d_flags :0; + d_name :'dmem'; + d_open :nil; + d_fdopen :nil; + d_close :nil; + d_read :nil; + d_write :nil; + d_ioctl :@dmem_ioctl; + d_poll :nil; + d_mmap :@dmem_mmap; + d_strategy :nil; + d_dump :nil; + d_kqfilter :nil; + d_purge :nil; + d_mmap_single:nil; + ); + +procedure dmemdev_init(); +var + i:Integer; +begin + For i:=0 to 2 do + begin + make_dev(@dmem_cdevsw,i,0,0,&777,'dmem%d',[i]); + end; +end; + + +end. + diff --git a/sys/dev/dev_null.pas b/sys/dev/dev_null.pas index 49b993a8..c2ac9e5e 100644 --- a/sys/dev/dev_null.pas +++ b/sys/dev/dev_null.pas @@ -13,9 +13,9 @@ const var zero_region:Pointer; - _zero_region:array[0..ZERO_REGION_SIZE-1] of Byte; procedure init_zero_region; +procedure free_zero_region; Function null_modevent(_mod,_type:Integer):Integer; //DEV_MODULE(nil, null_modevent, nil); @@ -109,7 +109,9 @@ begin end; end; else + begin error:=ENOIOCTL; + end; end; Exit(error); @@ -132,21 +134,36 @@ begin end; end; else + begin error:=ENOIOCTL; + end; end; Exit(error); end; procedure init_zero_region; +var + buf:Pointer; begin if (zero_region=nil) then begin - FillChar(_zero_region,SizeOf(_zero_region),0); - zero_region:=@_zero_region; + buf:=AllocMem(ZERO_REGION_SIZE); + if (System.InterlockedCompareExchange(zero_region,buf,nil)<>nil) then + begin + FreeMem(buf); + end; end; end; +procedure free_zero_region; +var + buf:Pointer; +begin + buf:=System.InterlockedExchange(zero_region,nil); + FreeMem(buf); +end; + { ARGSUSED } Function zero_read(dev:p_cdev;uio:p_uio;ioflag:Integer):Integer; var @@ -188,6 +205,7 @@ begin begin destroy_dev(null_dev); destroy_dev(zero_dev); + free_zero_region; end; MOD_SHUTDOWN:; diff --git a/sys/dev/dev_tty.pas b/sys/dev/dev_tty.pas index d6e4214e..e4144259 100644 --- a/sys/dev/dev_tty.pas +++ b/sys/dev/dev_tty.pas @@ -33,7 +33,7 @@ var } Function ttydev_open(dev:p_cdev;oflags,devtype:Integer):Integer; begin - Writeln('ttydev_open(',dev^.si_name,',',oflags,',',devtype,')'); + Writeln('ttydev_open("',dev^.si_name,'",',oflags,',',devtype,')'); Result:=0; end; @@ -110,7 +110,7 @@ begin else; end; - Writeln('ttydev_ioctl(0',dev^.si_name,',0x',HexStr(cmd,8),',0x',HexStr(data),',0x',HexStr(fflag,8)); + Writeln('ttydev_ioctl("',dev^.si_name,'",0x',HexStr(cmd,8),',0x',HexStr(data),',0x',HexStr(fflag,8),')'); //error:=tty_ioctl(tp, cmd, data, fflag, td); //done: @@ -343,27 +343,27 @@ const * will be logged in the kernel message buffer. } - function tty_makedev(fmt:PChar;const Args:Array of const):p_cdev; register; - var - dev:p_cdev; - uid:uid_t; - gid:gid_t; - mode:mode_t; - begin - // User device. - uid :=0; - gid :=GID_TTY; - mode:=S_IRUSR or S_IWUSR or S_IWGRP; +function tty_makedev(fmt:PChar;const Args:Array of const):p_cdev; register; +var + dev:p_cdev; + uid:uid_t; + gid:gid_t; + mode:mode_t; +begin + // User device. + uid :=0; + gid :=GID_TTY; + mode:=S_IRUSR or S_IWUSR or S_IWGRP; - dev:=make_dev_cred(@ttydev_cdevsw, 0, uid, gid, mode, fmt, Args); + dev:=make_dev_cred(@ttydev_cdevsw, 0, uid, gid, mode, fmt, Args); - Result:=dev; - end; + Result:=dev; +end; procedure ttyconsdev_init(); begin dev_console:=make_dev_credf(MAKEDEV_ETERNAL, @ttyconsdev_cdevsw, 0, UID_ROOT, GID_WHEEL, &600, 'console',[]); - + // tty_makedev('deci_stderr',[]); tty_makedev('deci_stdin' ,[]); tty_makedev('deci_stdout',[]); diff --git a/sys/fs/devfs/devfs_vnops.pas b/sys/fs/devfs/devfs_vnops.pas index e3447aef..8c5976c9 100644 --- a/sys/fs/devfs/devfs_vnops.pas +++ b/sys/fs/devfs/devfs_vnops.pas @@ -227,7 +227,9 @@ begin if (devp^<>fp^.f_data) then begin if (dswp^<>nil) then + begin dev_relthread(devp^, ref^); + end; Exit(ENXIO); end; @@ -252,7 +254,9 @@ begin error:=0; datap^:=p^.cdpd_data; end else + begin error:=ENOENT; + end; Exit(error); end; @@ -390,7 +394,9 @@ begin error:=devfs_populate_vp(vp); if (error<>0) then + begin Exit(error); + end; i:=buflen^; dd:=vp^.v_data; @@ -500,7 +506,9 @@ var begin not_found:=0; if ((de^.de_flags and DE_DOOMED)<>0) then + begin not_found:=1; + end; if DEVFS_DE_DROP(de) then begin Assert(not_found=1,'DEVFS de dropped but not doomed'); @@ -632,7 +640,9 @@ loop: VI_UNLOCK(vp); if ((dev^.si_flags and SI_ETERNAL)<>0) then + begin vp^.v_vflag:=vp^.v_vflag or VV_ETERNALDEV; + end; vp^.v_op:=@devfs_specops; end else @@ -689,16 +699,22 @@ begin de:=vp^.v_data; if (vp^.v_type=VDIR) then + begin de:=de^.de_dir; + end; error:=vaccess(vp^.v_type, de^.de_mode, de^.de_uid, de^.de_gid, ap^.a_accmode, nil); if (error=0) then + begin Exit(0); + end; if (error<>EACCES) then Exit(error); { We do, however, allow access to the controlling terminal } if ((p_proc.p_flag and P_CONTROLT)=0) then + begin Exit(error); + end; //if (ap^.a_td^.td_proc^.p_session^.s_ttydp=de^.de_cdp) then // Exit(0); Exit(error); @@ -721,7 +737,9 @@ begin * XXX: insmntque1() failure. } if (vp^.v_data=nil) then + begin Exit(0); + end; { * Hack: a tty device that is a controlling terminal @@ -750,7 +768,9 @@ begin //end; //sx_xunlock(@proctree_lock); if (oldvp<>nil) then + begin vrele(oldvp); + end; { * We do not want to really close the device if it * is still in use unless we are trying to close it @@ -865,7 +885,9 @@ begin error:=devfs_populate_vp(vp); if (error<>0) then + begin Exit(error); + end; dmp:=VFSTODEVFS(vp^.v_mount); sx_xunlock(@dmp^.dm_lock); @@ -958,10 +980,12 @@ begin fgn:=data; p:=devtoname(dev); i:=strlen(p) + 1; + if (i > fgn^.len) then error:=EINVAL else error:=copyout(p, fgn^.buf, i); + td^.td_fpop:=fpop; dev_relthread(dev, ref); Exit(error); @@ -970,7 +994,9 @@ begin td^.td_fpop:=nil; dev_relthread(dev, ref); if (error=ENOIOCTL) then + begin error:=ENOTTY; + end; if (error=0) and (com=TIOCSCTTY) then begin vp:=fp^.f_vnode; @@ -995,7 +1021,9 @@ begin { Get rid of reference to old control tty } if (vpold<>nil) then + begin vrele(vpold); + end; end; Exit(error); end; @@ -1032,10 +1060,14 @@ begin error:=0; //error:=prison_check(td^.td_ucred, dcr); if (error=0) then + begin Exit(0); + end; { We do, however, allow access to the controlling terminal } if ((p_proc.p_flag and P_CONTROLT)=0) then + begin Exit(error); + end; //if (td^.td_proc^.p_session^.s_ttydp=cdp) then // Exit(0); Exit(error); @@ -1067,22 +1099,32 @@ begin vpp^:=nil; if ((flags and ISLASTCN)<>0) and (nameiop=RENAME) then + begin Exit(EOPNOTSUPP); + end; if (dvp^.v_type<>VDIR) then + begin Exit(ENOTDIR); + end; if (((flags and ISDOTDOT)<>0) and ((dvp^.v_vflag and VV_ROOT)<>0)) then + begin Exit(EIO); + end; error:=VOP_ACCESS(dvp, VEXEC); if (error<>0) then + begin Exit(error); + end; if (cnp^.cn_namelen=1) and (pname^='.') then begin if ((flags and ISLASTCN) and nameiop<>LOOKUP) then + begin Exit(EINVAL); + end; vpp^:=dvp; VREF(dvp); Exit(0); @@ -1091,7 +1133,9 @@ begin if ((flags and ISDOTDOT)<>0) then begin if ((flags and ISLASTCN)<>0) and (nameiop<>LOOKUP) then + begin Exit(EINVAL); + end; de:=devfs_parent_dirent(dd); if (de=nil) then Exit(ENOENT); @@ -1152,7 +1196,9 @@ begin devfs_unmount_final(dmp); if (cdev<>nil) then + begin dev_rel(cdev); + end; Exit(ENOENT); end; @@ -1190,13 +1236,17 @@ begin end; if (devfs_prison_check(de)<>0) then + begin Exit(ENOENT); + end; if (cnp^.cn_nameiop=DELETE) and ((flags and ISLASTCN)<>0) then begin error:=VOP_ACCESS(dvp, VWRITE); if (error<>0) then + begin Exit(error); + end; if (vpp^=dvp) then begin VREF(dvp); @@ -1428,7 +1478,9 @@ var fpop:p_file; begin if (uio^.uio_resid > DEVFS_IOSIZE_MAX) then + begin Exit(EINVAL); + end; td:=curkthread; fpop:=td^.td_fpop; @@ -1444,7 +1496,9 @@ begin foffset_lock_uio(fp, uio, flags or FOF_NOLOCK); error:=dsw^.d_read(dev, uio, ioflag); if (uio^.uio_resid<>resid) or ((error=0) and (resid<>0)) then + begin vfs_timestamp(@dev^.si_atime); + end; td^.td_fpop:=fpop; dev_relthread(dev, ref); @@ -1466,11 +1520,15 @@ begin tmp_ncookies:=nil; if (ap^.a_vp^.v_type<>VDIR) then + begin Exit(ENOTDIR); + end; uio:=ap^.a_uio; if (uio^.uio_offset < 0) then + begin Exit(EINVAL); + end; { * XXX: This is a temporary hack to get around this filesystem not @@ -1616,18 +1674,24 @@ begin begin de_cov:=devfs_find(dd, de^.de_dirent^.d_name, de^.de_dirent^.d_namlen, 0); if (de_cov<>nil) then + begin de_cov^.de_flags:=de_cov^.de_flags and (not DE_COVERED); + end; end; { We need to unlock dvp because devfs_delete() may lock it. } VOP_UNLOCK(vp, 0); if (dvp<>vp) then + begin VOP_UNLOCK(dvp, 0); + end; devfs_delete(dmp, de, 0); sx_xunlock(@dmp^.dm_lock); if (dvp<>vp) then + begin vn_lock(dvp, LK_EXCLUSIVE or LK_RETRY); + end; vn_lock(vp, LK_EXCLUSIVE or LK_RETRY); end else @@ -1712,7 +1776,9 @@ begin dev_unlock(); dev_rel(@cdp^.cdp_c); end else + begin dev_unlock(); + end; vn_lock(vp, LK_EXCLUSIVE or LK_RETRY); Exit(0); @@ -1781,7 +1847,9 @@ begin de:=vp^.v_data; if (vp^.v_type=VDIR) then + begin de:=de^.de_dir; + end; error:=0; c:=0; @@ -1874,12 +1942,16 @@ begin error:=0; //error:=priv_check(curkthread, PRIV_DEVFS_SYMLINK); if (error<>0) then + begin Exit(error); + end; dmp:=VFSTODEVFS(ap^.a_dvp^.v_mount); if (devfs_populate_vp(ap^.a_dvp)<>0) then + begin Exit(ENOENT); + end; dd:=ap^.a_dvp^.v_data; de_cov:=devfs_find(dd, ap^.a_cnp^.cn_nameptr, ap^.a_cnp^.cn_namelen, 0); @@ -1937,7 +2009,9 @@ begin td:=curkthread; if (uio^.uio_resid > DEVFS_IOSIZE_MAX) then + begin Exit(EINVAL); + end; fpop:=td^.td_fpop; error:=devfs_fp_check(fp, @dev, @dsw, @ref); @@ -1947,7 +2021,9 @@ begin ioflag:=fp^.f_flag and (O_NONBLOCK or O_DIRECT or O_FSYNC); if ((ioflag and O_DIRECT)<>0) then + begin ioflag:=ioflag or IO_DIRECT; + end; foffset_lock_uio(fp, uio, flags or FOF_NOLOCK); diff --git a/sys/kern/kern_dmem.pas b/sys/kern/kern_dmem.pas new file mode 100644 index 00000000..1d730b5a --- /dev/null +++ b/sys/kern/kern_dmem.pas @@ -0,0 +1,40 @@ +unit kern_dmem; + +{$mode ObjFPC}{$H+} +{$CALLING SysV_ABI_CDecl} + +interface + +function sys_dmem_container(d_pool_id:Integer):Integer; + +implementation + +uses + errno, + kern_thr; + +const + default_pool_id=1; + +function sys_dmem_container(d_pool_id:Integer):Integer; +var + td:p_kthread; +begin + td:=curkthread; + if (td=nil) then Exit(-1); + + td^.td_retval[0]:=default_pool_id; + Result:=0; + + if (d_pool_id<>-1) then + begin + //Result:=priv_check(td,0x2ad); + //(param < 3) + Exit(EPERM); + end; +end; + + + +end. + diff --git a/sys/kern/kern_exec.pas b/sys/kern/kern_exec.pas index 8f1f5de6..e7c96c76 100644 --- a/sys/kern/kern_exec.pas +++ b/sys/kern/kern_exec.pas @@ -56,7 +56,8 @@ uses kern_event, machdep, kern_dlsym, - kern_authinfo; + kern_authinfo, + vfs_syscalls; function exec_alloc_args(args:p_image_args):Integer; begin @@ -1197,6 +1198,13 @@ begin Exit(0); end; +procedure init_tty; +begin + kern_openat(STDIN_FILENO ,'/dev/deci_stdin' ,UIO_SYSSPACE,O_RDWR,0); + kern_openat(STDOUT_FILENO,'/dev/deci_stdout',UIO_SYSSPACE,O_RDWR,0); + kern_openat(STDERR_FILENO,'/dev/deci_stderr',UIO_SYSSPACE,O_RDWR,0); +end; + const fexecv_proc_title='(fexecv)'; @@ -1422,6 +1430,9 @@ begin //copy authinfo g_authinfo:=imgp^.authinfo; + //init std tty + init_tty; + { * Free any resources malloc'd earlier that we didn't use. } diff --git a/sys/kern/kern_sysctl.pas b/sys/kern/kern_sysctl.pas index d6c0c5a9..90532197 100644 --- a/sys/kern/kern_sysctl.pas +++ b/sys/kern/kern_sysctl.pas @@ -414,6 +414,12 @@ begin if (pid<>g_pid) then Exit(EINVAL); + //G_APPINFO.mmap_flags:=G_APPINFO.mmap_flags or 1; + if (p_proc.p_sce_replay_exec<>0) then + begin + G_APPINFO.mmap_flags:=G_APPINFO.mmap_flags or 2; + end; + //sceSblACMgrIsSystemUcred()!=0 -> any proc //sceSblACMgrIsSystemUcred()==0 -> cur proc @@ -425,6 +431,10 @@ begin if (Result=0) then begin G_APPINFO:=APPINFO; + if (p_proc.p_sce_replay_exec<>0) then + begin + G_APPINFO.mmap_flags:=G_APPINFO.mmap_flags or 2; + end; end; end; diff --git a/sys/kern/kern_thr.pas b/sys/kern/kern_thr.pas index a062fdae..d26fadce 100644 --- a/sys/kern/kern_thr.pas +++ b/sys/kern/kern_thr.pas @@ -544,12 +544,16 @@ end; procedure PROC_INIT; +const + osreldate=$000DBBA0; begin FillChar(p_proc,SizeOf(p_proc),0); mtx_init(p_proc.p_mtx,'process lock'); knlist_init_mtx(@p_proc.p_klist,@p_proc.p_mtx); + p_proc.p_osrel:=osreldate; + p_proc.p_randomized_path:='system'; p_proc.p_ptc:=rdtsc; diff --git a/sys/sys_sysinit.pas b/sys/sys_sysinit.pas index c27b6e82..68a52351 100644 --- a/sys/sys_sysinit.pas +++ b/sys/sys_sysinit.pas @@ -40,7 +40,8 @@ uses vfs_mountroot, kern_conf, dev_null, - dev_tty; + dev_tty, + dev_dmem; var daemon_thr:p_kthread; @@ -74,6 +75,7 @@ begin // null_modevent(0,MOD_LOAD); ttyconsdev_init(); + dmemdev_init(); end; //Manual order of lazy initialization diff --git a/sys/syscalls.pas b/sys/syscalls.pas index b80ffe7d..9f4f3afd 100644 --- a/sys/syscalls.pas +++ b/sys/syscalls.pas @@ -205,6 +205,7 @@ function budget_delete(key:Integer):Integer; function budget_get(key:Integer;ptr:Pointer;psize:PInteger):Integer; function budget_set(key:Integer):Integer; function is_in_sandbox():Integer; +function dmem_container(d_pool_id:Integer):Integer; function get_authinfo(pid:Integer;info:Pointer):Integer; function mname(addr:Pointer;len:QWORD;name:PChar):Integer; function dynlib_dlsym(handle:Integer;symbol:pchar;addrp:ppointer):Integer; @@ -1632,6 +1633,13 @@ asm jmp cerror end; +function dmem_container(d_pool_id:Integer):Integer; assembler; nostackframe; +asm + movq $586,%rax + call fast_syscall + jmp cerror +end; + function get_authinfo(pid:Integer;info:Pointer):Integer; assembler; nostackframe; asm movq $587,%rax diff --git a/sys/sysent.pas b/sys/sysent.pas index 28f71c20..cb630622 100644 --- a/sys/sysent.pas +++ b/sys/sysent.pas @@ -13,6 +13,7 @@ uses kern_evf, kern_gpo, kern_sig, + kern_dmem, kern_exec, kern_exit, kern_osem, @@ -2986,7 +2987,7 @@ const ), (//[586] sy_narg:1; - sy_call:nil; + sy_call:@sys_dmem_container; sy_name:'sys_dmem_container' ), (//[587] diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi index 6eae88d8..cfd1755b 100644 --- a/sys/test/project1.lpi +++ b/sys/test/project1.lpi @@ -633,6 +633,14 @@ + + + + + + + + diff --git a/sys/test/project1.lpr b/sys/test/project1.lpr index 05b658d2..44f3199a 100644 --- a/sys/test/project1.lpr +++ b/sys/test/project1.lpr @@ -95,7 +95,8 @@ uses kern_sysctl, kern_budget, kern_regmgr, - kern_authinfo; + kern_authinfo, + kern_dmem; const PAGE_MAP_COUNT=(qword(VM_MAXUSER_ADDRESS) shr PAGE_SHIFT); diff --git a/sys/vfs/vfile.pas b/sys/vfs/vfile.pas index 7ca6c267..4dbd3838 100644 --- a/sys/vfs/vfile.pas +++ b/sys/vfs/vfile.pas @@ -105,6 +105,10 @@ const DFLAG_PASSABLE=$01; { may be passed via unix sockets. } DFLAG_SEEKABLE=$02; { seekable / nonsequential } + STDIN_FILENO =0; // standard input file descriptor + STDOUT_FILENO=1; // standard output file descriptor + STDERR_FILENO=2; // standard error file descriptor + type mode_t=Integer; uid_t =Integer; diff --git a/sys/vfs/vsys_generic.pas b/sys/vfs/vsys_generic.pas index 39024174..b0e50bcf 100644 --- a/sys/vfs/vsys_generic.pas +++ b/sys/vfs/vsys_generic.pas @@ -126,7 +126,9 @@ var begin error:=fget_read(fd, CAP_READ or CAP_SEEK, @fp); if (error<>0) then + begin Exit(error); + end; error:=dofileread(fd, fp, auio, -1, 0); fdrop(fp); Exit(error); @@ -139,7 +141,9 @@ var begin error:=fget_read(fd, CAP_READ, @fp); if (error<>0) then + begin Exit(error); + end; if ((fp^.f_ops^.fo_flags and DFLAG_SEEKABLE)=0) then error:=ESPIPE else @@ -147,6 +151,7 @@ begin error:=EINVAL else error:=dofileread(fd, fp, auio, offset, FOF_OFFSET); + fdrop(fp); Exit(error); end; @@ -158,7 +163,9 @@ var begin error:=fget_write(fd, CAP_WRITE or CAP_SEEK, @fp); if (error<>0) then + begin Exit(error); + end; error:=dofilewrite(fd, fp, auio, -1, 0); fdrop(fp); Exit(error); @@ -171,7 +178,9 @@ var begin error:=fget_write(fd, CAP_WRITE, @fp); if (error<>0) then + begin Exit(error); + end; if ((fp^.f_ops^.fo_flags and DFLAG_SEEKABLE)=0) then error:=ESPIPE else @@ -179,6 +188,7 @@ begin error:=EINVAL else error:=dofilewrite(fd, fp, auio, offset, FOF_OFFSET); + fdrop(fp); Exit(error); end; @@ -234,7 +244,9 @@ var begin error:=copyinuio(iovp, iovcnt, @auio); if (error<>0) then + begin Exit(error); + end; error:=kern_readv(fd, auio); FreeMem(auio); Exit(error); @@ -250,7 +262,9 @@ var begin error:=copyinuio(iovp, iovcnt, @auio); if (error<>0) then + begin Exit(error); + end; error:=kern_preadv(fd, auio, offset); FreeMem(auio); Exit(error); @@ -282,7 +296,9 @@ begin if (error<>0) then begin if (auio^.uio_resid<>cnt) and ((error=ERESTART) or (error=EINTR) or (error=EWOULDBLOCK)) then + begin error:=0; + end; end; Dec(cnt,auio^.uio_resid); @@ -339,7 +355,9 @@ var begin error:=copyinuio(iovp, iovcnt, @auio); if (error<>0) then + begin Exit(error); + end; error:=kern_writev(fd, auio); FreeMem(auio); Exit(error); @@ -355,7 +373,9 @@ var begin error:=copyinuio(iovp, iovcnt, @auio); if (error<>0) then + begin Exit(error); + end; error:=kern_pwritev(fd, auio, offset); FreeMem(auio); Exit(error); @@ -385,7 +405,9 @@ begin if (error<>0) then begin if (auio^.uio_resid<>cnt) and ((error=ERESTART) or (error=EINTR) or (error=EWOULDBLOCK)) then + begin error:=0; + end; { Socket layer is responsible for issuing SIGPIPE. } if (fp^.f_type<>DTYPE_SOCKET) and (error=EPIPE) then begin @@ -412,10 +434,14 @@ var error:Integer; begin if (length < 0) then + begin Exit(EINVAL); + end; error:=fget(fd, CAP_FTRUNCATE, @fp); if (error<>0) then + begin Exit(error); + end; if ((fp^.f_flag and FWRITE)=0) then begin fdrop(fp); @@ -441,7 +467,9 @@ var begin error:=fget(fd, CAP_IOCTL, @fp); if (error<>0) then + begin Exit(error); + end; if ((fp^.f_flag and (FREAD or FWRITE))=0) then begin fdrop(fp); @@ -461,19 +489,23 @@ begin FIONBIO: begin tmp:=PInteger(data)^; + if (tmp<>0) then atomic_set_int(@fp^.f_flag, FNONBLOCK) else atomic_clear_int(@fp^.f_flag, FNONBLOCK); + data:=@tmp; end; FIOASYNC: begin tmp:=PInteger(data)^; + if (tmp<>0) then atomic_set_int(@fp^.f_flag, FASYNC) else atomic_clear_int(@fp^.f_flag, FASYNC); + data:=@tmp; end; end; @@ -490,6 +522,7 @@ var smalldata:array[0..SYS_IOCTL_SMALL_SIZE-1] of Byte; //__aligned(SYS_IOCTL_SMALL_ALIGN) arg,error:Integer; size:DWORD; + kern_data:Pointer; begin if (com > $ffffffff) then begin @@ -506,7 +539,9 @@ begin ((com and (IOC_VOID or IOC_IN or IOC_OUT))=0) or (((com and (IOC_IN or IOC_OUT))<>0) and (size=0)) or (((com and IOC_VOID)<>0) and (size > 0) and (size<>sizeof(Integer))) then + begin Exit(ENOTTY); + end; if (size > 0) then begin @@ -514,22 +549,26 @@ begin begin { Integer argument. } arg:=ptrint(data); - data:=@arg; + kern_data:=@arg; size:=0; end else begin if (size > SYS_IOCTL_SMALL_SIZE) then - data:=AllocMem(size) + kern_data:=AllocMem(size) else - data:=@smalldata; + kern_data:=@smalldata; end; end else - data:=@data; + begin + kern_data:=@curkthread^.td_frame.tf_rsi; + end; if ((com and IOC_IN)<>0) then begin - error:=copyin(data, data, size); + error:=copyin(data, kern_data, size); if (error<>0) then + begin goto _out; + end; end else if ((com and IOC_OUT)<>0) then begin @@ -537,17 +576,21 @@ begin * Zero the buffer so the user always * gets back something deterministic. } - FillChar(data,size,0); + FillChar(kern_data^,size,0); end; - error:=kern_ioctl(fd, com, data); + error:=kern_ioctl(fd, com, kern_data); if (error=0) and ((com and IOC_OUT)<>0) then - error:=copyout(data, data, size); + begin + error:=copyout(kern_data, data, size); + end; _out: if (size > SYS_IOCTL_SMALL_SIZE) then - FreeMem(data); + begin + FreeMem(kern_data); + end; Exit(error); end; @@ -561,7 +604,9 @@ begin * of specific filesystem implementations. } if (events and (not POLLSTANDARD))<>0 then + begin Exit(POLLNVAL); + end; Exit(events and (POLLIN or POLLOUT or POLLRDNORM or POLLWRNORM)); end; @@ -585,7 +630,9 @@ begin begin error:=kern_sigprocmask(td, SIG_SETMASK, uset, @td^.td_oldsigmask, 0); if (error<>0) then + begin Exit(error); + end; td^.td_pflags:=td^.td_pflags or TDP_OLDMASK; { * Make sure that ast() is called on Exitto @@ -613,19 +660,27 @@ begin begin error:=copyin(uts, @ts, sizeof(ts)); if (error<>0) then + begin Exit(error); + end; TIMESPEC_TO_TIMEVAL(@tv, @ts); tvp:=@tv; end else + begin tvp:=nil; + end; if (sm<>nil) then begin error:=copyin(sm, @_set, sizeof(_set)); if (error<>0) then + begin Exit(error); + end; uset:=@_set; end else + begin uset:=nil; + end; Exit(kern_pselect(nd, uin, uou, uex, tvp, uset, NFDBITS)); end; @@ -639,7 +694,9 @@ begin begin error:=copyin(utv, @tv, sizeof(tv)); if (error<>0) then + begin Exit(error); + end; tvp:=@tv; end else tvp:=nil; @@ -663,7 +720,9 @@ var bits:Byte; begin if (nd >= ndu) or (fd_in=nil) then + begin Exit(0); + end; oaddr:=nil; bits:=0; { silence gcc } @@ -675,12 +734,16 @@ begin begin res:=fubyte(addr^); if (res=-1) then + begin Exit(EFAULT); + end; oaddr:=addr; bits:=res; end; if ((bits and (1 shl (i mod NBBY)))<>0) then + begin Exit(EBADF); + end; end; Exit(0); end; @@ -714,7 +777,9 @@ var begin error2:=copyout(@obits[x], name, ncpubytes); if (error2<>0) then + begin error:=error2; + end; end; end; @@ -731,13 +796,19 @@ begin error:=select_check_badfd(fd_in, nd, ndu, abi_nfdbits); if (error<>0) then + begin Exit(error); + end; error:=select_check_badfd(fd_ou, nd, ndu, abi_nfdbits); if (error<>0) then + begin Exit(error); + end; error:=select_check_badfd(fd_ex, nd, ndu, abi_nfdbits); if (error<>0) then + begin Exit(error); + end; { * Allocate just enough bits for the non-nil fd_sets. Use the @@ -749,11 +820,17 @@ begin nbufbytes:=0; if (fd_in<>nil) then + begin Inc(nbufbytes,2 * ncpbytes); + end; if (fd_ou<>nil) then + begin Inc(nbufbytes,2 * ncpbytes); + end; if (fd_ex<>nil) then + begin Inc(nbufbytes,2 * ncpbytes); + end; if (nbufbytes <= sizeof(s_selbits)) then selbits:=@s_selbits[0] @@ -789,12 +866,16 @@ begin repeat error:=selscan(td, @ibits, @obits, nd); if (error<>0) or (td^.td_retval[0]<>0) then + begin break; + end; if (atv<>0) then begin rtv:=get_unit_uptime; if (rtv>=atv) then + begin break; + end; ttv:=atv-rtv; if (ttv>24*60*60*hz) then @@ -804,19 +885,27 @@ begin end; error:=seltdwait(td, timo); if (error<>0) then + begin break; + end; error:=selrescan(td, @ibits, @obits); if (error<>0) or (td^.td_retval[0]<>0) then + begin break; + end; until false; seltdclear(td); done: { select is not restarted after signals... } if (error=ERESTART) then + begin error:=EINTR; + end; if (error=EWOULDBLOCK) then + begin error:=0; + end; if (error=0) then begin @@ -826,7 +915,9 @@ done: end; if (selbits<>@s_selbits[0]) then + begin FreeMem(selbits); + end; Exit(error); end; @@ -902,7 +993,9 @@ var begin fp:=fget_unlocked(fd); if (fp=nil) then + begin Exit(EBADF); + end; { * If the file descriptor is for a capability, test rights and use * the file descriptor references by the capability. @@ -958,7 +1051,9 @@ begin end; error:=getselfd_cap(fd, @fp); if (error<>0) then + begin Exit(error); + end; idx:=fd div NFDBITS; bit:=fd_mask(1) shl (fd mod NFDBITS); ev:=fo_poll(fp, selflags(ibits, idx, bit)); @@ -1032,16 +1127,22 @@ var ni:QWORD; begin if (nfds > maxfilesperproc) and (nfds > FD_SETSIZE) then + begin Exit(EINVAL); + end; td:=curkthread; ni:=nfds * sizeof(t_pollfd); + if (ni > sizeof(smallbits)) then bits:=AllocMem(ni) else bits:=@smallbits; + error:=copyin(fds, bits, ni); if (error<>0) then + begin goto done; + end; if (timeout<>INFTIM) then begin atv:=USEC_TO_UNIT(_msec2usec(timeout)); @@ -1072,28 +1173,40 @@ begin end; error:=seltdwait(td, timo); if (error<>0) then + begin break; + end; error:=pollrescan(td); if (error<>0) or (td^.td_retval[0]<>0) then + begin break; + end; until false; seltdclear(td); done: { poll is not restarted after signals... } if (error=ERESTART) then + begin error:=EINTR; + end; if (error=EWOULDBLOCK) then + begin error:=0; + end; if (error=0) then begin error:=_pollout(td, bits, fds, nfds); if (error<>0) then + begin goto _out; + end; end; _out: if (ni > sizeof(smallbits)) then + begin FreeMem(bits); + end; Exit(error); end; @@ -1129,7 +1242,9 @@ begin if (cap_funwrap(fp, CAP_POLL_EVENT, @fp)<>0) then begin if (fp<>nil) then + begin fdrop(fp); + end; // fd^.revents:=POLLNVAL; Inc(n); @@ -1144,7 +1259,9 @@ begin } fd^.revents:=fo_poll(fp, fd^.events); if (fd^.revents<>0) then + begin Inc(n); + end; // fdrop(fp); // @@ -1168,9 +1285,13 @@ begin begin error:=copyout(@fds^.revents, @ufds^.revents, sizeof(ufds^.revents)); if (error<>0) then + begin Exit(error); + end; if (fds^.revents<>0) then + begin Inc(n); + end; Inc(fds); Inc(ufds); end; @@ -1217,14 +1338,20 @@ begin * set simultaneously with POLLHUP. } if ((fds^.revents and POLLHUP)<>0) then + begin fds^.revents:=fds^.revents and (not POLLOUT); + end; if (fds^.revents<>0) then + begin Inc(n); + end; end; // if (fp<>nil) then + begin fdrop(fp); + end; end; // Inc(i); @@ -1245,11 +1372,15 @@ var begin stp:=td^.td_sel; if (stp^.st_free1=nil) then + begin stp^.st_free1:=AllocMem(SizeOf(t_selfd)); + end; stp^.st_free1^.sf_td:=stp; stp^.st_free1^.sf_cookie:=cookie; if (stp^.st_free2=nil) then + begin stp^.st_free2:=AllocMem(SizeOf(t_selfd)); + end; stp^.st_free2^.sf_td:=stp; stp^.st_free2^.sf_cookie:=cookie; end; @@ -1259,7 +1390,9 @@ begin STAILQ_REMOVE(@stp^.st_selq,sfp,@sfp^.sf_link); mtx_lock(sfp^.sf_mtx^); if (sfp^.sf_si<>nil) then + begin TAILQ_REMOVE(@sfp^.sf_si^.si_tdlist,sfp,@sfp^.sf_threads); + end; mtx_unlock(sfp^.sf_mtx^); FreeMem(sfp); end; @@ -1292,19 +1425,23 @@ begin * Don't record when doing a rescan. } if ((stp^.st_flags and SELTD_RESCAN)<>0) then + begin Exit; + end; { * Grab one of the preallocated descriptors. } sfp:=stp^.st_free1; if (sfp<>nil) then + begin stp^.st_free1:=nil - else + end else begin sfp:=stp^.st_free2; if (sfp<>nil) then + begin stp^.st_free2:=nil - else + end else begin Assert(false,'selrecord: No free selfd on selq'); Exit; @@ -1312,7 +1449,9 @@ begin end; mtxp:=sip^.si_mtx; if (mtxp=nil) then + begin mtxp:=mtx_pool_find(mtxpool_select, sip); + end; { * Initialize the sfp and queue it in the thread. } @@ -1359,7 +1498,9 @@ var begin { If it's not initialized there can't be any waiters. } if (sip^.si_mtx=nil) then + begin Exit; + end; { * Locking the selinfo locks all selfds associated with it. } @@ -1393,7 +1534,9 @@ var begin stp:=td^.td_sel; if (stp<>nil) then + begin goto _out; + end; stp:=AllocMem(sizeof(t_seltd)); td^.td_sel:=stp; mtx_init(stp^.st_mtx, 'sellck'); @@ -1423,10 +1566,12 @@ begin mtx_unlock(stp^.st_mtx); Exit(0); end; + if (timo > 0) then error:=_cv_timedwait_sig(@stp^.st_wait, @stp^.st_mtx, timo) else error:=_cv_wait_sig(@stp^.st_wait, @stp^.st_mtx); + mtx_unlock(stp^.st_mtx); Exit(error); @@ -1438,11 +1583,17 @@ var begin stp:=td^.td_sel; if (stp=nil) then + begin Exit; + end; if (stp^.st_free1<>nil) then + begin FreeMem(stp^.st_free1); + end; if (stp^.st_free2<>nil) then + begin FreeMem(stp^.st_free2); + end; td^.td_sel:=nil; FreeMem(stp); end;