diff options
Diffstat (limited to 'sys/fs/devfs/devfs_vnops.c')
-rw-r--r-- | sys/fs/devfs/devfs_vnops.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index 09a978a..dbce518 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -61,6 +61,7 @@ #include <sys/proc.h> #include <sys/stat.h> #include <sys/sx.h> +#include <sys/sysctl.h> #include <sys/time.h> #include <sys/ttycom.h> #include <sys/unistd.h> @@ -113,6 +114,25 @@ static vop_symlink_t devfs_symlink; extern struct vop_vector devfs_vnodeops; extern struct vop_vector devfs_specops; +static u_int +devfs_random(void) +{ + static u_int devfs_seed; + + while (devfs_seed == 0) { + /* + * Make sure people don't make stupid assumptions + * about device major/minor numbers in userspace. + * We do this late to get entropy and for the same + * reason we force a reseed, but it may not be + * late enough for entropy to be available. + */ + arc4rand(&devfs_seed, sizeof devfs_seed, 1); + devfs_seed &= 0xf0f; + } + return (devfs_seed); +} + static int devfs_fp_check(struct file *fp, struct cdev **devp, struct cdevsw **dswp) { @@ -441,7 +461,8 @@ devfs_getattr(ap) vap->va_mtime = dev->si_mtime; fix(dev->si_ctime); vap->va_ctime = dev->si_ctime; - vap->va_rdev = dev->si_udev; + + vap->va_rdev = de->de_inode ^ devfs_random(); } vap->va_gen = 0; vap->va_flags = 0; @@ -1432,6 +1453,43 @@ static struct vop_vector devfs_specops = { .vop_write = VOP_PANIC, }; +dev_t +dev2udev(struct cdev *x) +{ + if (x == NULL) + return (NODEV); + return (x->si_inode ^ devfs_random()); +} + +/* + * Helper sysctl for devname(3). We're given a struct cdev * and return + * the name, if any, registered by the device driver. + */ +static int +sysctl_devname(SYSCTL_HANDLER_ARGS) +{ + int error; + dev_t ud; + struct cdev *dev, **dp; + + error = SYSCTL_IN(req, &ud, sizeof (ud)); + if (error) + return (error); + if (ud == NODEV) + return(EINVAL); + dp = devfs_itod(ud ^ devfs_random()); + if (dp == NULL) + return(ENOENT); + dev = *dp; + if (dev == NULL) + return(ENOENT); + return(SYSCTL_OUT(req, dev->si_name, strlen(dev->si_name) + 1)); + return (error); +} + +SYSCTL_PROC(_kern, OID_AUTO, devname, CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY, + NULL, 0, sysctl_devname, "", "devname(3) handler"); + /* * Our calling convention to the device drivers used to be that we passed * vnode.h IO_* flags to read()/write(), but we're moving to fcntl.h O_ |