mknod(2): Restrict functionality to creating FIFOs.
authorSascha Wildner <saw@online.de>
Thu, 20 Dec 2012 02:57:05 +0000 (03:57 +0100)
committerSascha Wildner <saw@online.de>
Thu, 20 Dec 2012 02:57:05 +0000 (03:57 +0100)
Now that we have devfs(5) for handling our device nodes, we can retire
part of mknod(2) functionality and restrict it to what POSIX requires:

"The only portable use of mknod() is to create a FIFO-special file.
 If mode is not S_IFIFO or dev is not 0, the behavior of mknod() is
 unspecified."

In-discussion-with: beket

sys/emulation/linux/linux_misc.c
sys/kern/vfs_syscalls.c
sys/sys/kern_syscall.h

index 1d304e4..095d959 100644 (file)
@@ -1094,17 +1094,14 @@ sys_linux_mknod(struct linux_mknod_args *args)
                    path, args->mode, args->dev);
 #endif
        get_mplock();
-       error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
-       if (error == 0) {
-               if (args->mode & S_IFIFO) {
+       if ((args->mode & S_IFIFO) == 0 || args->dev != 0) {
+               error = EINVAL;
+       } else {
+               error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
+               if (error == 0)
                        error = kern_mkfifo(&nd, args->mode);
-               } else {
-                       error = kern_mknod(&nd, args->mode,
-                                          umajor(args->dev),
-                                          uminor(args->dev));
-               }
+               nlookup_done(&nd);
        }
-       nlookup_done(&nd);
        rel_mplock();
 
        linux_free_path(&path);
@@ -1128,18 +1125,15 @@ sys_linux_mknodat(struct linux_mknodat_args *args)
                    path, args->mode, args->dev);
 #endif
        get_mplock();
-       dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
-       error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, 0);
-       if (error == 0) {
-               if (args->mode & S_IFIFO) {
+       if ((args->mode & S_IFIFO) == 0 || args->dev != 0) {
+               error = EINVAL;
+       } else {
+               dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
+               error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, 0);
+               if (error == 0)
                        error = kern_mkfifo(&nd, args->mode);
-               } else {
-                       error = kern_mknod(&nd, args->mode,
-                                          umajor(args->dev),
-                                          uminor(args->dev));
-               }
+               nlookup_done_at(&nd, fp);
        }
-       nlookup_done_at(&nd, fp);
        rel_mplock();
 
        linux_free_path(&path);
index dc144d2..e66090e 100644 (file)
@@ -1976,74 +1976,6 @@ sys_openat(struct openat_args *uap)
        return (error);
 }
 
-int
-kern_mknod(struct nlookupdata *nd, int mode, int rmajor, int rminor)
-{
-       struct thread *td = curthread;
-       struct proc *p = td->td_proc;
-       struct vnode *vp;
-       struct vattr vattr;
-       int error;
-       int whiteout = 0;
-
-       KKASSERT(p);
-
-       VATTR_NULL(&vattr);
-       vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask;
-       vattr.va_rmajor = rmajor;
-       vattr.va_rminor = rminor;
-
-       switch (mode & S_IFMT) {
-       case S_IFMT:    /* used by badsect to flag bad sectors */
-               error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_BAD, 0);
-               vattr.va_type = VBAD;
-               break;
-       case S_IFCHR:
-               error = priv_check(td, PRIV_VFS_MKNOD_DEV);
-               vattr.va_type = VCHR;
-               break;
-       case S_IFBLK:
-               error = priv_check(td, PRIV_VFS_MKNOD_DEV);
-               vattr.va_type = VBLK;
-               break;
-       case S_IFWHT:
-               error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_WHT, 0);
-               whiteout = 1;
-               break;
-       case S_IFDIR:   /* special directories support for HAMMER */
-               error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_DIR, 0);
-               vattr.va_type = VDIR;
-               break;
-       default:
-               error = EINVAL;
-               break;
-       }
-
-       if (error)
-               return (error);
-
-       bwillinode(1);
-       nd->nl_flags |= NLC_CREATE | NLC_REFDVP;
-       if ((error = nlookup(nd)) != 0)
-               return (error);
-       if (nd->nl_nch.ncp->nc_vp)
-               return (EEXIST);
-       if ((error = ncp_writechk(&nd->nl_nch)) != 0)
-               return (error);
-
-       if (whiteout) {
-               error = VOP_NWHITEOUT(&nd->nl_nch, nd->nl_dvp,
-                                     nd->nl_cred, NAMEI_CREATE);
-       } else {
-               vp = NULL;
-               error = VOP_NMKNOD(&nd->nl_nch, nd->nl_dvp,
-                                  &vp, nd->nl_cred, &vattr);
-               if (error == 0)
-                       vput(vp);
-       }
-       return (error);
-}
-
 /*
  * mknod_args(char *path, int mode, int dev)
  *
@@ -2055,12 +1987,14 @@ sys_mknod(struct mknod_args *uap)
        struct nlookupdata nd;
        int error;
 
-       error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
-       if (error == 0) {
-               error = kern_mknod(&nd, uap->mode,
-                                  umajor(uap->dev), uminor(uap->dev));
+       if ((uap->mode & S_IFIFO) == 0 || uap->dev != 0) {
+               error = EINVAL;
+       } else {
+               error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
+               if (error == 0)
+                       error = kern_mkfifo(&nd, uap->mode);
+               nlookup_done(&nd);
        }
-       nlookup_done(&nd);
        return (error);
 }
 
@@ -2077,12 +2011,15 @@ sys_mknodat(struct mknodat_args *uap)
        struct file *fp;
        int error;
 
-       error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
-       if (error == 0) {
-               error = kern_mknod(&nd, uap->mode,
-                                  umajor(uap->dev), uminor(uap->dev));
+       if ((uap->mode & S_IFIFO) == 0 || uap->dev != 0) {
+               error = EINVAL;
+       } else {
+               error = nlookup_init_at(&nd, &fp, uap->fd, uap->path,
+                   UIO_USERSPACE, 0);
+               if (error == 0)
+                       error = kern_mkfifo(&nd, uap->mode);
+               nlookup_done_at(&nd, fp);
        }
-       nlookup_done_at(&nd, fp);
        return (error);
 }
 
index 6e3cacf..ffff2cf 100644 (file)
@@ -148,7 +148,6 @@ int kern_mountctl(const char *path, int op, struct file *fp,
                 void *buf, int buflen, int *res);
 int kern_mkdir(struct nlookupdata *nd, int mode);
 int kern_mkfifo(struct nlookupdata *nd, int mode);
-int kern_mknod(struct nlookupdata *nd, int mode, int rmajor, int rminor);
 int kern_open(struct nlookupdata *nd, int flags, int mode, int *res);
 int kern_close(int fd);
 int kern_closefrom(int fd);