Module Name: src Committed By: riastradh Date: Mon Oct 3 19:12:51 UTC 2022
Modified Files: src/sys/dev: cons.c Log Message: cons(9): Serialize open and close. Kernel lock wasn't enough for this -- cdevvp, vn_lock, or VOP_OPEN could block, allowing another thread to re-enter open. To generate a diff of this commit: cvs rdiff -u -r1.80 -r1.81 src/sys/dev/cons.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/cons.c diff -u src/sys/dev/cons.c:1.80 src/sys/dev/cons.c:1.81 --- src/sys/dev/cons.c:1.80 Mon Oct 3 19:12:29 2022 +++ src/sys/dev/cons.c Mon Oct 3 19:12:51 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: cons.c,v 1.80 2022/10/03 19:12:29 riastradh Exp $ */ +/* $NetBSD: cons.c,v 1.81 2022/10/03 19:12:51 riastradh Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cons.c,v 1.80 2022/10/03 19:12:29 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cons.c,v 1.81 2022/10/03 19:12:51 riastradh Exp $"); #include <sys/param.h> #include <sys/proc.h> @@ -53,6 +53,7 @@ __KERNEL_RCSID(0, "$NetBSD: cons.c,v 1.8 #include <sys/vnode.h> #include <sys/kauth.h> #include <sys/mutex.h> +#include <sys/module.h> #include <dev/cons.h> @@ -83,6 +84,8 @@ const struct cdevsw cons_cdevsw = { .d_flag = D_TTY }; +static struct kmutex cn_lock; + struct tty *constty = NULL; /* virtual console output device */ struct consdev *cn_tab; /* physical console device info */ struct vnode *cn_devvp[2]; /* vnode for underlying device. */ @@ -113,8 +116,12 @@ cnopen(dev_t dev, int flag, int mode, st if (unit > 1) return ENODEV; - if (cn_tab == NULL) - return (0); + mutex_enter(&cn_lock); + + if (cn_tab == NULL) { + error = 0; + goto out; + } /* * always open the 'real' console device, so we don't get nailed @@ -145,15 +152,19 @@ cnopen(dev_t dev, int flag, int mode, st */ panic("cnopen: cn_tab->cn_dev == dev"); } - if (cn_devvp[unit] != NULLVP) - return 0; + if (cn_devvp[unit] != NULLVP) { + error = 0; + goto out; + } if ((error = cdevvp(cndev, &cn_devvp[unit])) != 0) { printf("cnopen: unable to get vnode reference\n"); - return error; + goto out; } vn_lock(cn_devvp[unit], LK_EXCLUSIVE | LK_RETRY); error = VOP_OPEN(cn_devvp[unit], flag, kauth_cred_get()); VOP_UNLOCK(cn_devvp[unit]); + +out: mutex_exit(&cn_lock); return error; } @@ -165,8 +176,12 @@ cnclose(dev_t dev, int flag, int mode, s unit = minor(dev); - if (cn_tab == NULL) - return (0); + mutex_enter(&cn_lock); + + if (cn_tab == NULL) { + error = 0; + goto out; + } vp = cn_devvp[unit]; cn_devvp[unit] = NULL; @@ -174,6 +189,8 @@ cnclose(dev_t dev, int flag, int mode, s error = VOP_CLOSE(vp, flag, kauth_cred_get()); VOP_UNLOCK(vp); vrele(vp); + +out: mutex_exit(&cn_lock); return error; } @@ -433,3 +450,21 @@ cn_redirect(dev_t *devp, int is_read, in *devp = dev; return true; } + +MODULE(MODULE_CLASS_DRIVER, cons, NULL); + +static int +cons_modcmd(modcmd_t cmd, void *arg) +{ + + switch (cmd) { + case MODULE_CMD_INIT: + mutex_init(&cn_lock, MUTEX_DEFAULT, IPL_NONE); + return 0; + case MODULE_CMD_FINI: + mutex_destroy(&cn_lock); + return 0; + default: + return ENOTTY; + } +}