git: 9535d9f104d8 - main - libc: add helper furnction to set sysctl() user.* variables
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 05 Feb 2022 12:43:46 UTC
The branch main has been updated by se: URL: https://cgit.FreeBSD.org/src/commit/?id=9535d9f104d82487abfc3a64de18f9d010bba6d2 commit 9535d9f104d82487abfc3a64de18f9d010bba6d2 Author: Stefan Eßer <se@FreeBSD.org> AuthorDate: 2022-02-05 12:33:53 +0000 Commit: Stefan Eßer <se@FreeBSD.org> CommitDate: 2022-02-05 12:33:53 +0000 libc: add helper furnction to set sysctl() user.* variables Testing had revealed that trying to retrieve the user.localbase variable into to small a buffer would return the correct error code, but would not fill the available buffer space with a partial result. A partial result is of no use, but this is still a violation of the documented behavior, which has been fixed in the previous commit to this function. I just checked the code for "user.cs_path" and found that it had the same issue. Instead of fixing the logic for each user.* sysctl string variable individually, this commit adds a helper function set_user_str() that implements the semantics specified in the sysctl() man page. It is currently only used for "user.cs_path" and "user.localbase", but it will offer a significant simplification when further such variables will be added (as I intend to do). MFC after: 3 days --- lib/libc/gen/sysctl.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/lib/libc/gen/sysctl.c b/lib/libc/gen/sysctl.c index 9dd80ddfc0d8..59242b50bbed 100644 --- a/lib/libc/gen/sysctl.c +++ b/lib/libc/gen/sysctl.c @@ -46,6 +46,25 @@ __FBSDID("$FreeBSD$"); extern int __sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp, const void *newp, size_t newlen); +static int +set_user_str(void *dstp, size_t *dstlenp, const char *src, size_t len, + size_t maxlen) +{ + int retval; + + retval = 0; + if (dstp != NULL) { + if (len > maxlen) { + len = maxlen; + errno = ENOMEM; + retval = -1; + } + memcpy(dstp, src, len); + } + *dstlenp = len; + return (retval); +} + int sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp, const void *newp, size_t newlen) @@ -74,18 +93,10 @@ sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp, /* Variables under CLT_USER that may be overridden by kernel values */ switch (name[1]) { case USER_LOCALBASE: - if (oldlenp != NULL && *oldlenp == 1) { - *oldlenp = sizeof(_PATH_LOCALBASE); - if (oldp != NULL) { - if (*oldlenp > orig_oldlen) { - *oldlenp = orig_oldlen; - errno = ENOMEM; - retval = -1; - } - memmove(oldp, _PATH_LOCALBASE, *oldlenp); - } - } - return (retval); + if (oldlenp == NULL || *oldlenp > sizeof("")) + return (0); + return (set_user_str(oldp, oldlenp, _PATH_LOCALBASE, + sizeof(_PATH_LOCALBASE), orig_oldlen)); } /* Variables under CLT_USER whose values are immutably defined below */ @@ -96,14 +107,8 @@ sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp, switch (name[1]) { case USER_CS_PATH: - if (oldp != NULL && orig_oldlen < sizeof(_PATH_STDPATH)) { - errno = ENOMEM; - return (-1); - } - *oldlenp = sizeof(_PATH_STDPATH); - if (oldp != NULL) - memmove(oldp, _PATH_STDPATH, sizeof(_PATH_STDPATH)); - return (0); + return (set_user_str(oldp, oldlenp, _PATH_STDPATH, + sizeof(_PATH_STDPATH), orig_oldlen)); } if (oldp != NULL && *oldlenp < sizeof(int)) {