Download raw body.
sysctl(2), video(4): unlock sysctl_video()
On Sun, 15 Dec 2024 21:47:20 +0100,
Vitaliy Makkoveev <mvs@openbsd.org> wrote:
>
> This sysctl(2) path contains only `video_record_enable', which is
> atomically accessed boolean integer.
>
Works as expected, no regression found.
FWIW ok kirill@
> Index: sys/dev/video.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/video.c,v
> diff -u -p -r1.58 video.c
> --- sys/dev/video.c 15 Dec 2024 18:23:56 -0000 1.58
> +++ sys/dev/video.c 15 Dec 2024 20:28:01 -0000
> @@ -38,6 +38,7 @@
>
> /*
> * Locks used to protect struct members and global data
> + * a atomic
> * m sc_mtx
> */
>
> @@ -93,7 +94,7 @@ struct cfdriver video_cd = {
> /*
> * Global flag to control if video recording is enabled by kern.video.record.
> */
> -int video_record_enable = 0;
> +int video_record_enable = 0; /* [a] */
>
> int
> videoprobe(struct device *parent, void *match, void *aux)
> @@ -234,7 +235,7 @@ videoread(dev_t dev, struct uio *uio, in
>
> /* move no more than 1 frame to userland, as per specification */
> size = ulmin(uio->uio_resid, sc->sc_fsize);
> - if (!video_record_enable)
> + if (!atomic_load_int(&video_record_enable))
> bzero(sc->sc_fbuffer, size);
> error = uiomove(sc->sc_fbuffer, size, uio);
> if (error)
> @@ -371,7 +372,7 @@ videoioctl(dev_t dev, u_long cmd, caddr_
> }
> error = (sc->hw_if->dqbuf)(sc->hw_hdl,
> (struct v4l2_buffer *)data);
> - if (!video_record_enable)
> + if (!atomic_load_int(&video_record_enable))
> bzero(sc->sc_fbuffer_mmap + vb->m.offset, vb->length);
> mtx_enter(&sc->sc_mtx);
> sc->sc_frames_ready--;
> Index: sys/kern/kern_sysctl.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
> diff -u -p -r1.457 kern_sysctl.c
> --- sys/kern/kern_sysctl.c 15 Dec 2024 18:25:12 -0000 1.457
> +++ sys/kern/kern_sysctl.c 15 Dec 2024 20:28:01 -0000
> @@ -161,6 +161,10 @@ void fill_kproc(struct process *, struct
>
> int kern_sysctl_locked(int *, u_int, void *, size_t *, void *, size_t,
> struct proc *);
> +int kern_sysctl_dirs(int, int *, u_int, void *, size_t *, void *,
> + size_t, struct proc *);
> +int kern_sysctl_dirs_locked(int, int *, u_int, void *, size_t *, void *,
> + size_t, struct proc *);
> int hw_sysctl_locked(int *, u_int, void *, size_t *,void *, size_t,
> struct proc *);
>
> @@ -395,6 +399,38 @@ int
> kern_sysctl_dirs(int top_name, int *name, u_int namelen,
> void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p)
> {
> + size_t savelen;
> + int error;
> +
> + switch (top_name) {
> +#if NAUDIO > 0
> + case KERN_AUDIO:
> + return (sysctl_audio(name, namelen, oldp, oldlenp,
> + newp, newlen));
> +#endif
> +#if NVIDEO > 0
> + case KERN_VIDEO:
> + return (sysctl_video(name, namelen, oldp, oldlenp,
> + newp, newlen));
> +#endif
> + default:
> + break;
> + }
> +
> + savelen = *oldlenp;
> + if ((error = sysctl_vslock(oldp, savelen)))
> + return (error);
> + error = kern_sysctl_dirs_locked(top_name, name, namelen,
> + oldp, oldlenp, newp, newlen, p);
> + sysctl_vsunlock(oldp, savelen);
> +
> + return (error);
> +}
> +
> +int
> +kern_sysctl_dirs_locked(int top_name, int *name, u_int namelen,
> + void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p)
> +{
> switch (top_name) {
> #ifndef SMALL_KERNEL
> case KERN_PROC:
> @@ -462,11 +498,6 @@ kern_sysctl_dirs(int top_name, int *name
> return witness_sysctl(name, namelen, oldp, oldlenp,
> newp, newlen);
> #endif
> -#if NVIDEO > 0
> - case KERN_VIDEO:
> - return (sysctl_video(name, namelen, oldp, oldlenp,
> - newp, newlen));
> -#endif
> case KERN_CPUSTATS:
> return (sysctl_cpustats(name, namelen, oldp, oldlenp,
> newp, newlen));
> @@ -489,25 +520,9 @@ kern_sysctl(int *name, u_int namelen, vo
> size_t savelen;
>
> /* dispatch the non-terminal nodes first */
> - if (namelen != 1) {
> - switch (name[0]) {
> -#if NAUDIO > 0
> - case KERN_AUDIO:
> - return (sysctl_audio(name + 1, namelen - 1,
> - oldp, oldlenp, newp, newlen));
> -#endif
> - default:
> - break;
> - }
> -
> - savelen = *oldlenp;
> - if ((error = sysctl_vslock(oldp, savelen)))
> - return (error);
> - error = kern_sysctl_dirs(name[0], name + 1, namelen - 1,
> - oldp, oldlenp, newp, newlen, p);
> - sysctl_vsunlock(oldp, savelen);
> - return (error);
> - }
> + if (namelen != 1)
> + return (kern_sysctl_dirs(name[0], name + 1, namelen - 1,
> + oldp, oldlenp, newp, newlen, p));
>
> switch (name[0]) {
> case KERN_ALLOWKMEM:
>
--
wbr, Kirill
sysctl(2), video(4): unlock sysctl_video()