tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Adding truncate/ftruncate length argument checks



Hi,

According to the OpenGroup online doccuments for truncate[1] and
ftruncate[2], there are a few cases where both syscalls should fail
when given some length values :

- EINVAL for negative length.
- EFBIG (or EINVAL) for length bigger than process file size limit.

But our implementation do not handle both cases ... and the syscalls
succeed where it should not.

The attached patch add the missing length argument checks, and update
the man page accordingly.

[1] http://pubs.opengroup.org/onlinepubs/009695399/functions/truncate.html
[2] http://pubs.opengroup.org/onlinepubs/009695399/functions/ftruncate.html

-- 
Nicolas Joly

Biology IT Center
Institut Pasteur, Paris.
Index: sys/kern/vfs_syscalls.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.476
diff -u -p -r1.476 vfs_syscalls.c
--- sys/kern/vfs_syscalls.c     15 Feb 2014 22:32:16 -0000      1.476
+++ sys/kern/vfs_syscalls.c     26 Feb 2014 14:34:00 -0000
@@ -135,6 +135,8 @@ static int fd_nameiat(struct lwp *, int,
 static int fd_nameiat_simple_user(struct lwp *, int, const char *,
     namei_simple_flags_t, struct vnode **);
 
+static int valid_truncate_length(struct lwp *, off_t);
+
 
 /*
  * This table is used to maintain compatibility with 4.3BSD
@@ -3899,6 +3901,22 @@ do_sys_utimes(struct lwp *l, struct vnod
        return do_sys_utimens(l, vp, path, flag, tsptr, UIO_SYSSPACE);
 }
 
+static int
+valid_truncate_length(struct lwp *l, off_t length)
+{
+
+       if (length < 0)
+               return EINVAL;
+       if (length > l->l_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
+               mutex_enter(proc_lock);
+               psignal(l->l_proc, SIGXFSZ);
+               mutex_exit(proc_lock);
+               return EFBIG;
+       }
+
+       return 0;
+}
+
 /*
  * Truncate a file given its path name.
  */
@@ -3915,6 +3933,9 @@ sys_truncate(struct lwp *l, const struct
        struct vattr vattr;
        int error;
 
+       if ((error = valid_truncate_length(l, SCARG(uap, length))) != 0)
+               return error;
+
        error = namei_simple_user(SCARG(uap, path),
                                NSM_FOLLOW_TRYEMULROOT, &vp);
        if (error != 0)
@@ -3949,6 +3970,9 @@ sys_ftruncate(struct lwp *l, const struc
        file_t *fp;
        int error;
 
+       if ((error = valid_truncate_length(l, SCARG(uap, length))) != 0)
+               return error;
+
        /* fd_getvnode() will use the descriptor for us */
        if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
                return (error);
Index: lib/libc/sys/truncate.2
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/truncate.2,v
retrieving revision 1.26
diff -u -p -r1.26 truncate.2
--- lib/libc/sys/truncate.2     31 May 2010 12:16:20 -0000      1.26
+++ lib/libc/sys/truncate.2     26 Feb 2014 14:34:00 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)truncate.2 8.1 (Berkeley) 6/4/93
 .\"
-.Dd March 16, 2008
+.Dd February 26, 2014
 .Dt TRUNCATE 2
 .Os
 .Sh NAME
@@ -76,6 +76,14 @@ and
 .Fn ftruncate
 are:
 .Bl -tag -width Er
+.It Bq Er EFBIG
+The
+.Fa length
+argument exceeds the process's file size limit.
+.It Bq Er EINVAL
+The
+.Fa length
+argument is less than 0.
 .It Bq Er EISDIR
 The named file is a directory.
 .It Bq Er EROFS


Home | Main Index | Thread Index | Old Index