From 5f31b145b29afa4d23f77b01b024bd0ecaf3a016 Mon Sep 17 00:00:00 2001 From: guenther Date: Sat, 18 May 2024 05:20:22 +0000 Subject: [PATCH] Add pathconfat(2): pathconf(2) but with at-fd and flags arguments, the latter supporting the ability to get timestamp resolution of symlinks. ok deraadt@ millert@ --- include/unistd.h | 5 ++- lib/libc/Symbols.list | 2 + lib/libc/hidden/unistd.h | 3 +- lib/libc/shlib_version | 2 +- lib/libc/sys/Makefile.inc | 4 +- lib/libc/sys/pathconf.2 | 93 ++++++++++++++++++++++++++++++++++++--- sys/kern/kern_pledge.c | 3 +- sys/kern/syscalls.master | 5 ++- sys/kern/vfs_syscalls.c | 37 +++++++++++++--- usr.bin/kdump/kdump.c | 3 +- 10 files changed, 138 insertions(+), 19 deletions(-) diff --git a/include/unistd.h b/include/unistd.h index b87979ebbff..1fda33a9cda 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: unistd.h,v 1.108 2023/12/12 15:30:55 deraadt Exp $ */ +/* $OpenBSD: unistd.h,v 1.109 2024/05/18 05:20:22 guenther Exp $ */ /* $NetBSD: unistd.h,v 1.26.4.1 1996/05/28 02:31:51 mrg Exp $ */ /*- @@ -357,6 +357,9 @@ int isatty(int); int link(const char *, const char *); off_t lseek(int, off_t, int); long pathconf(const char *, int); +#if __BSD_VISIBLE +long pathconfat(int, const char *, int, int); +#endif int pause(void); int pipe(int *); ssize_t read(int, void *, size_t) diff --git a/lib/libc/Symbols.list b/lib/libc/Symbols.list index b1e7e916bbc..eb4d78cc947 100644 --- a/lib/libc/Symbols.list +++ b/lib/libc/Symbols.list @@ -157,6 +157,7 @@ _thread_sys_nfssvc _thread_sys_open _thread_sys_openat _thread_sys_pathconf +_thread_sys_pathconfat _thread_sys_pipe _thread_sys_pipe2 _thread_sys_pledge @@ -359,6 +360,7 @@ nfssvc open openat pathconf +pathconfat pipe pipe2 pledge diff --git a/lib/libc/hidden/unistd.h b/lib/libc/hidden/unistd.h index 74918f59675..f81cece3dd7 100644 --- a/lib/libc/hidden/unistd.h +++ b/lib/libc/hidden/unistd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: unistd.h,v 1.13 2023/12/12 15:30:55 deraadt Exp $ */ +/* $OpenBSD: unistd.h,v 1.14 2024/05/18 05:20:22 guenther Exp $ */ /* * Copyright (c) 2015 Philip Guenther * @@ -110,6 +110,7 @@ PROTO_NORMAL(mkstemp); PROTO_NORMAL(nfssvc); PROTO_DEPRECATED(nice); PROTO_NORMAL(pathconf); +PROTO_NORMAL(pathconfat); /*PROTO_CANCEL(pause);*/ PROTO_NORMAL(pipe); PROTO_NORMAL(pipe2); diff --git a/lib/libc/shlib_version b/lib/libc/shlib_version index 9a3cbbdfde6..670da2562f6 100644 --- a/lib/libc/shlib_version +++ b/lib/libc/shlib_version @@ -1,4 +1,4 @@ major=100 -minor=0 +minor=1 # note: If changes were made to include/thread_private.h or if system calls # were added/changed then librthread/shlib_version must also be updated. diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index ff0ca6dc558..0e022f11687 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.178 2024/03/29 06:48:04 deraadt Exp $ +# $OpenBSD: Makefile.inc,v 1.179 2024/05/18 05:20:22 guenther Exp $ # $NetBSD: Makefile.inc,v 1.35 1995/10/16 23:49:07 jtc Exp $ # @(#)Makefile.inc 8.1 (Berkeley) 6/17/93 @@ -62,7 +62,7 @@ ASM= __semctl.o __thrsigdivert.o \ mknod.o mknodat.o mlock.o mlockall.o mmap.o mount.o mprotect.o \ mquery.o msgctl.o msgget.o munlock.o munlockall.o munmap.o \ nfssvc.o \ - pathconf.o pipe.o pipe2.o pledge.o profil.o \ + pathconf.o pathconfat.o pipe.o pipe2.o pledge.o profil.o \ quotactl.o \ readlink.o readlinkat.o reboot.o \ rename.o renameat.o revoke.o rmdir.o \ diff --git a/lib/libc/sys/pathconf.2 b/lib/libc/sys/pathconf.2 index 099f3bb5be1..8be0618a7ed 100644 --- a/lib/libc/sys/pathconf.2 +++ b/lib/libc/sys/pathconf.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pathconf.2,v 1.25 2018/06/21 20:30:36 jmc Exp $ +.\" $OpenBSD: pathconf.2,v 1.26 2024/05/18 05:20:22 guenther Exp $ .\" $NetBSD: pathconf.2,v 1.2 1995/02/27 12:35:22 cgd Exp $ .\" .\" Copyright (c) 1993 @@ -30,11 +30,12 @@ .\" .\" @(#)pathconf.2 8.1 (Berkeley) 6/4/93 .\" -.Dd $Mdocdate: June 21 2018 $ +.Dd $Mdocdate: May 18 2024 $ .Dt PATHCONF 2 .Os .Sh NAME .Nm pathconf , +.Nm pathconfat , .Nm fpathconf .Nd get configurable pathname variables .Sh SYNOPSIS @@ -43,9 +44,13 @@ .Fn pathconf "const char *path" "int name" .Ft long .Fn fpathconf "int fd" "int name" +.In fcntl.h +.Ft long +.Fn pathconfat "int fd" "const char *path" "int name" "int flag" .Sh DESCRIPTION The -.Fn pathconf +.Fn pathconf , +.Fn pathconfat , and .Fn fpathconf functions provide a method for applications to determine the current @@ -132,9 +137,48 @@ Returns 1 if synchronized I/O is supported, otherwise 0. .It Dv _PC_TIMESTAMP_RESOLUTION The resolution in nanoseconds of file timestamps. .El +.Pp +The +.Fn pathconfat +function is equivalent to +.Fn pathconf +except in the case where +.Fa path +specifies a relative path. +In this case the file to be changed is determined relative to the directory +associated with the file descriptor +.Fa fd +instead of the current working directory. +.Pp +If +.Fn pathconfat +is passed the special value +.Dv AT_FDCWD +(defined in +.In fcntl.h ) +in the +.Fa fd +parameter, the current working directory is used. +If +.Fa flag +is also zero, the behavior is identical to a call to +.Fn pathconf . +.Pp +The +.Fa flag +argument is the bitwise OR of zero or more of the following values: +.Pp +.Bl -tag -width AT_SYMLINK_NOFOLLOW -offset indent -compact +.It Dv AT_SYMLINK_NOFOLLOW +If +.Fa path +names a symbolic link, then the system variable for the symbolic +link is queried. +.El .Sh RETURN VALUES If the call to -.Fn pathconf +.Fn pathconf , +.Fn pathconfat , or .Fn fpathconf is not successful, \-1 is returned and @@ -147,7 +191,8 @@ is not modified. Otherwise, the current variable value is returned. .Sh ERRORS If any of the following conditions occur, the -.Fn pathconf +.Fn pathconf , +.Fn pathconfat , and .Fn fpathconf functions shall return \-1 and set @@ -166,6 +211,8 @@ An I/O error occurred while reading from the file system. .El .Pp .Fn pathconf +and +.Fn pathconfat will fail if: .Bl -tag -width Er .It Bq Er ENOTDIR @@ -190,6 +237,38 @@ Too many symbolic links were encountered in translating the pathname. points outside the process's allocated address space. .El .Pp +Additionally, the +.Fn pathconfat +function will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value of the +.Fa flag +argument was neither zero nor +.Dv AT_SYMLINK_NOFOLLOW . +.It Bq Er EBADF +The +.Fa path +argument specifies a relative path and the +.Fa fd +argument is neither +.Dv AT_FDCWD +nor a valid file descriptor. +.It Bq Er ENOTDIR +The +.Fa path +argument specifies a relative path and the +.Fa fd +argument is a valid file descriptor but it does not reference a directory. +.It Bq Er EACCES +The +.Fa path +argument specifies a relative path but search permission is denied +for the directory which the +.Fa fd +file descriptor references. +.El +.Pp .Fn fpathconf will fail if: .Bl -tag -width Er @@ -214,3 +293,7 @@ and .Fn fpathconf functions first appeared in .Bx 4.4 . +The +.Fn pathconfat +function first appeared in +.Ox 7.6 . diff --git a/sys/kern/kern_pledge.c b/sys/kern/kern_pledge.c index dce4d91ccf9..487df5dc249 100644 --- a/sys/kern/kern_pledge.c +++ b/sys/kern/kern_pledge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_pledge.c,v 1.313 2024/04/05 13:55:26 deraadt Exp $ */ +/* $OpenBSD: kern_pledge.c,v 1.314 2024/05/18 05:20:22 guenther Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott @@ -340,6 +340,7 @@ const uint64_t pledge_syscalls[SYS_MAXSYSCALL] = { [SYS_statfs] = PLEDGE_RPATH, [SYS_fstatfs] = PLEDGE_RPATH, [SYS_pathconf] = PLEDGE_RPATH, + [SYS_pathconfat] = PLEDGE_RPATH, [SYS_utimes] = PLEDGE_FATTR, [SYS_futimes] = PLEDGE_FATTR, diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 55f484967fc..ddc1fabf842 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -1,4 +1,4 @@ -; $OpenBSD: syscalls.master,v 1.263 2024/05/10 09:21:01 claudio Exp $ +; $OpenBSD: syscalls.master,v 1.264 2024/05/18 05:20:22 guenther Exp $ ; $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $ ; @(#)syscalls.master 8.2 (Berkeley) 1/13/94 @@ -346,7 +346,8 @@ 187 OBSOL lfs_segwait 188 OBSOL stat35 189 OBSOL fstat35 -190 OBSOL lstat35 +190 STD { long sys_pathconfat(int fd, const char *path, \ + int name, int flag); } 191 STD { long sys_pathconf(const char *path, int name); } 192 STD { long sys_fpathconf(int fd, int name); } 193 STD { int sys_swapctl(int cmd, const void *arg, int misc); } diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 40445f251bf..abd4395bc46 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.364 2024/03/25 17:57:07 guenther Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.365 2024/05/18 05:20:22 guenther Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -76,6 +76,7 @@ int dosymlinkat(struct proc *, const char *, int, const char *); int dounlinkat(struct proc *, int, const char *, int); int dofaccessat(struct proc *, int, const char *, int, int); int dofstatat(struct proc *, int, const char *, struct stat *, int); +int dopathconfat(struct proc *, int, const char *, int, int, register_t *); int doreadlinkat(struct proc *, int, const char *, char *, size_t, register_t *); int dochflagsat(struct proc *, int, const char *, u_int, int); @@ -2112,16 +2113,42 @@ sys_pathconf(struct proc *p, void *v, register_t *retval) syscallarg(const char *) path; syscallarg(int) name; } */ *uap = v; - int error; + + return dopathconfat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, name), + 0, retval); +} + +int +sys_pathconfat(struct proc *p, void *v, register_t *retval) +{ + struct sys_pathconfat_args /* { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(int) name; + syscallarg(int) flag; + } */ *uap = v; + + return dopathconfat(p, SCARG(uap, fd), SCARG(uap, path), + SCARG(uap, name), SCARG(uap, flag), retval); +} + +int +dopathconfat(struct proc *p, int fd, const char *path, int name, int flag, + register_t *retval) +{ + int follow, error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, - SCARG(uap, path), p); + if (flag & ~AT_SYMLINK_NOFOLLOW) + return EINVAL; + + follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; + NDINITAT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fd, path, p); nd.ni_pledge = PLEDGE_RPATH; nd.ni_unveil = UNVEIL_READ; if ((error = namei(&nd)) != 0) return (error); - error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval); + error = VOP_PATHCONF(nd.ni_vp, name, retval); vput(nd.ni_vp); return (error); } diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index 8091934474d..c28ad9eb2e0 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kdump.c,v 1.162 2024/03/29 07:53:32 deraadt Exp $ */ +/* $OpenBSD: kdump.c,v 1.163 2024/05/18 05:20:22 guenther Exp $ */ /*- * Copyright (c) 1988, 1993 @@ -866,6 +866,7 @@ static const formatter scargs[][8] = { [SYS_setgid] = { Gidname }, [SYS_setegid] = { Gidname }, [SYS_seteuid] = { Uidname }, + [SYS_pathconfat] = { Atfd, Ppath, Pathconfname, Atflagsname }, [SYS_pathconf] = { Ppath, Pathconfname }, [SYS_fpathconf] = { Pfd, Pathconfname }, [SYS_swapctl] = { Swapctlname, Pptr, Pdecint }, -- 2.20.1