The branch main has been updated by se:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=e11ad014d1468729ecf758ab3709618a78feae1b

commit e11ad014d1468729ecf758ab3709618a78feae1b
Author:     Stefan Eßer <[email protected]>
AuthorDate: 2022-02-04 12:44:20 +0000
Commit:     Stefan Eßer <[email protected]>
CommitDate: 2022-02-04 12:44:20 +0000

    libc: return partial sysctl() result if buffer is too small
    
    Testing of a new feature revealed that calling sysctl() to retrieve
    the value of the user.localbase variable passing too low a buffer size
    could leave the result buffer unchanged.
    
    The behavior in the normal case of a sufficiently large buffer was
    correct.
    
    All known callers pass a sufficiently large buffer and have thus not
    been affected by this issue. If a non-default value had been assigned
    to this variable, the result was as documented, too.
    
    Fix the function to fill the buffer with a partial result, if the
    passed in buffer size is too low to hold the full result.
    
    MFC after:      3 days
---
 lib/libc/gen/sysctl.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/lib/libc/gen/sysctl.c b/lib/libc/gen/sysctl.c
index cdd2d3e391e6..9dd80ddfc0d8 100644
--- a/lib/libc/gen/sysctl.c
+++ b/lib/libc/gen/sysctl.c
@@ -74,17 +74,18 @@ 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)
-                       return (0);
-               if (oldp != NULL) {
-                       if (orig_oldlen < sizeof(_PATH_LOCALBASE)) {
-                               errno = ENOMEM;
-                               return (-1);
+               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);
                        }
-                       memmove(oldp, _PATH_LOCALBASE, sizeof(_PATH_LOCALBASE));
                }
-               *oldlenp = sizeof(_PATH_LOCALBASE);
-               return (0);
+               return (retval);
        }
 
        /* Variables under CLT_USER whose values are immutably defined below */

Reply via email to