kern/99758: chown/chmod pty slave side in kernel

Atsuo Ohki ohki at gssm.otsuka.tsukuba.ac.jp
Tue Jul 4 02:50:20 UTC 2006


>Number:         99758
>Category:       kern
>Synopsis:       chown/chmod pty slave side in kernel
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jul 04 02:50:14 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Atsuo Ohki
>Release:        FreeBSD 6.1
>Organization:
GSSM, University of Tsukuba, Tokyo
>Environment:
FreeBSD smr01 6.1-RELEASE-p2 FreeBSD 6.1-RELEASE-p2 #3: Mon Jul  3 15:55:22 JST 2006     ohki at smr01:/usr/src/sys/i386/compile/SMP  i386
>Description:
I know that the ownership and permission of the pty slave side can be
controlled by `grantpt()' (with a set-uided helper program /usr/libexec/pt_chown),
but all programs which manipulate control/slave pair of pty do not
use `grantpt()'. More over, `grantpt()' leave the onwership of pty slave as
those of user who used the slave last time.

I though it is better to control the ownership and permission of the pty slave
as follow:
 1) when the control side is opened, set the ownership of the corresponding
    slave to those who opend the control side, and the permission as 0620.
 2) when the control side is closed, restore the ownership/permission of the
    corresponding slave to root/wheel, 0666.

Included patch modifies kern/tty_pty.c, fs/devfs/devfs_devs.c,
fs/devfs/devfs_vfsops.c

>How-To-Repeat:

>Fix:
--- kern/tty_pty.c-ORIG Fri Mar 31 01:46:56 2006
+++ kern/tty_pty.c      Sun Jul  2 22:49:29 2006
@@ -265,6 +265,8 @@
        }
 }
 
+extern void devfs_update(struct cdev *dev, uid_t uid, gid_t gid, int mode);
+
 static int
 ptcopen(struct cdev *dev, int flag, int devtype, struct thread *td)
 {
@@ -288,6 +290,9 @@
        pt->pt_flags = 0;
        pt->pt_send = 0;
        pt->pt_ucntl = 0;
+
+       devfs_update(pt->devs, td->td_ucred->cr_ruid, 4, 0620);
+
        return (0);
 }
 
@@ -311,6 +316,11 @@
                tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
                tp->t_state |= TS_ZOMBIE;
                ttyflush(tp, FREAD | FWRITE);
+       }
+
+       {
+               struct ptsc *pt = dev->si_drv1;
+               devfs_update(pt->devs, UID_ROOT, GID_WHEEL, 0666);
        }
 
        tp->t_oproc = 0;                /* mark closed */
--- fs/devfs/devfs_devs.c-ORIG  Mon Mar 13 12:05:06 2006
+++ fs/devfs/devfs_devs.c       Mon Jul  3 10:45:18 2006
@@ -490,6 +490,43 @@
        devfs_generation++;
 }
 
+extern int devfs_sx_xlock(u_int idx);
+extern void devfs_sx_xunlock(u_int idx);
+void devfs_update(struct cdev *dev, uid_t uid, gid_t gid, int mode);
+
+void
+devfs_update(struct cdev *dev, uid_t uid, gid_t gid, int mode)
+{
+       struct cdev_priv *cdp;
+       struct devfs_dirent *de;
+       u_int i;
+
+       cdp = dev->si_priv;
+       dev_lock();
+       if (dev != &cdp->cdp_c || cdp->cdp_dirents == NULL)
+               goto out;
+
+       dev->si_uid = uid;
+       dev->si_gid = gid;
+       dev->si_mode = mode;
+
+       for (i=0; i <= cdp->cdp_maxdirent; i++) {
+               if ((de = cdp->cdp_dirents[i]) != NULL &&
+                   de->de_cdp == cdp && de->de_dirent->d_type == DT_CHR) {
+                       dev_unlock();
+                       if (devfs_sx_xlock(i)) {
+                               de->de_uid = uid;
+                               de->de_gid = gid;
+                               de->de_mode =mode;
+                               devfs_sx_xunlock(i);
+                       }
+                       dev_lock();
+               }
+       }
+out:
+       dev_unlock();
+}
+
 static void
 devfs_devs_init(void *junk __unused)
 {
--- fs/devfs/devfs_vfsops.c-ORIG        Mon Sep 26 23:36:52 2005
+++ fs/devfs/devfs_vfsops.c     Mon Jul  3 15:53:37 2006
@@ -61,6 +61,68 @@
 static vfs_statfs_t    devfs_statfs;
 
 /*
+ * stuff for devfs_update()
+ */
+#define DEVFS_IDX2MOUNTP_SIZE  16
+static struct devfs_mount *devfs_mountps[DEVFS_IDX2MOUNTP_SIZE];
+
+static inline void
+put_fmp(struct devfs_mount *dm)
+{
+       int i;
+
+       for (i=0; i<DEVFS_IDX2MOUNTP_SIZE; i++) {
+               if (devfs_mountps[i] == NULL) {
+                       devfs_mountps[i] = dm;
+                       return;
+               }
+       }
+}
+
+static inline void
+clear_fmp(struct devfs_mount *dm)
+{
+       int i;
+
+       for (i=0; i<DEVFS_IDX2MOUNTP_SIZE; i++) {
+               if (devfs_mountps[i] == dm) {
+                       devfs_mountps[i] = NULL;
+                       return;
+               }
+       }
+}
+
+int devfs_sx_xlock(u_int idx);
+void devfs_sx_xunlock(u_int idx);
+
+int
+devfs_sx_xlock(u_int idx) {
+       int i;
+
+       for (i=0; i<DEVFS_IDX2MOUNTP_SIZE; i++) {
+               if (devfs_mountps[i] != NULL &&
+                   devfs_mountps[i]->dm_idx == idx) {
+                       sx_xlock(&(devfs_mountps[i]->dm_lock));
+                       return (1);
+               }
+       }
+       return (0);
+}
+
+void
+devfs_sx_xunlock(u_int idx) {
+       int i;
+
+       for (i=0; i<DEVFS_IDX2MOUNTP_SIZE; i++) {
+               if (devfs_mountps[i] != NULL &&
+                   devfs_mountps[i]->dm_idx == idx) {
+                       sx_xunlock(&(devfs_mountps[i]->dm_lock));
+                       return;
+               }
+       }
+}
+
+/*
  * Mount the filesystem
  */
 static int
@@ -105,6 +167,8 @@
 
        vfs_mountedfrom(mp, "devfs");
 
+       put_fmp(fmp);   /* XXX */
+
        return (0);
 }
 
@@ -121,6 +185,7 @@
        if (error)
                return (error);
        sx_xlock(&fmp->dm_lock);
+       clear_fmp(fmp); /* XXX */
        devfs_cleanup(fmp);
        devfs_rules_cleanup(fmp);
        sx_xunlock(&fmp->dm_lock);

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list