[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 268479] lib/libc/stdlib/getenv.c may have a problem with putenv()"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 20 Dec 2022 03:23:54 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=268479
Bug ID: 268479
Summary: lib/libc/stdlib/getenv.c may have a problem with
putenv()
Product: Base System
Version: CURRENT
Hardware: Any
OS: Any
Status: New
Severity: Affects Only Me
Priority: ---
Component: standards
Assignee: standards@FreeBSD.org
Reporter: dclarke@blastwave.org
I am not sure this is a bug or simply expected behavior. However I see
strange results when I attempt to override the uname(3) struct members
with env vars such as UNAME_s if I use putenv 'UNAME_s=' for an empty
value.
Looking at lib/libc/stdlib/getenv.c I see :
000644 /* Create environment entry. */
000645 envVars[envNdx].name = string;
000646 envVars[envNdx].nameLen = -1;
000647 envVars[envNdx].value = NULL;
000648 envVars[envNdx].valueSize = -1;
000649 envVars[envNdx].putenv = true;
000650 envVars[envNdx].active = true;
000651 newEnvActive++;
Which seems to be fine with the insert of an env var of zero length.
However a zero length env var named UNAME_s will destroy the system
name.
What I see in a few simple tests :
(1) Trivial unsetenv
styx$ cat uname_unsetenv.c
/*
* uname_unsetenv.c Demonstrate that FreeBSD seems to allow env var
* values to override the uname(3) struct members.
* We may remove the env var contents with unsetenv.
*
* Copyright (C) Dennis Clarke 2022
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* https://www.gnu.org/licenses/gpl-3.0.txt
*/
/*********************************************************************
* The Open Group Base Specifications Issue 6
* IEEE Std 1003.1, 2004 Edition
*
* An XSI-conforming application should ensure that the feature
* test macro _XOPEN_SOURCE is defined with the value 600 before
* inclusion of any header. This is needed to enable the
* functionality described in The _POSIX_C_SOURCE Feature Test
* Macro and in addition to enable the XSI extension.
*
*********************************************************************/
#define _XOPEN_SOURCE 600
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/utsname.h>
int main(int argc, char *argv[])
{
int j;
struct utsname uname_data;
char *env_var_value = NULL;
/* tricky stuff about UNAME(3) :
*
* These ENVIRONMENT variables override some uname struct members
*
* env name overrides
* --------------------------
* UNAME_s sysname
* UNAME_r release
* UNAME_v version
* UNAME_m machine
*
*/
char *env_var[] = {"UNAME_s","UNAME_r","UNAME_v","UNAME_m"};
setlocale( LC_MESSAGES, "C" );
/* check for and then unset those env vars */
errno = 0;
for ( j=0; j<4 ; j++ ) {
env_var_value = getenv(env_var[j]);
if ( env_var_value != NULL) {
fprintf(stderr, "INFO : env var \"%s\" set to \"%s\"\n",
env_var[j], env_var_value);
if (unsetenv(env_var[j]) < 0) {
fprintf(stderr, "FAIL : could not clear env \"%s\"\n",
env_var[j]);
perror("FAIL : ");
return EXIT_FAILURE;
} else {
fprintf(stderr, " : cleared env var \"%s\"\n", env_var[j]);
}
}
}
if ( uname( &uname_data ) < 0 ) {
fprintf(stderr,
"WARNING : Could not attain system uname data.\n" );
perror ("uname" );
} else {
printf("-------------------------------" );
printf("------------------------------\n" );
printf(" system name = %s\n", uname_data.sysname );
printf(" node name = %s\n", uname_data.nodename );
printf(" release = %s\n", uname_data.release );
printf(" version = %s\n", uname_data.version );
printf(" machine = %s\n", uname_data.machine );
printf ( "-------------------------------" );
printf ( "------------------------------" );
}
printf ("\n");
return EXIT_SUCCESS;
}
Here is the system uname data :
styx$ uname -apKU
FreeBSD styx 14.0-CURRENT FreeBSD 14.0-CURRENT #0 main-n259756-6692670f58f9:
Mon Dec 19 16:48:48 UTC 2022
root@styx:/usr/obj/usr/src/amd64.amd64/sys/GENERIC amd64 amd64 1400075 1400075
styx$ ./uname_unsetenv
-------------------------------------------------------------
system name = FreeBSD
node name = styx
release = 14.0-CURRENT
version = FreeBSD 14.0-CURRENT #0 main-n259756-6692670f58f9: Mon
Dec 19 16:48:48 UTC 2022 root@styx:/usr/obj/usr/src/amd64.amd64/sys/GENERIC
machine = amd64
-------------------------------------------------------------
styx$
We can pollute the uname struct members in FreeBSD :
styx$ UNAME_s=system UNAME_m=alpha64 UNAME_r=random uname -apKU
system styx random FreeBSD 14.0-CURRENT #0 main-n259756-6692670f58f9: Mon Dec
19 16:48:48 UTC 2022 root@styx:/usr/obj/usr/src/amd64.amd64/sys/GENERIC
alpha64 amd64 1400075 1400075
The above code will remove the offending env vars :
styx$ UNAME_s=system UNAME_m=alpha64 UNAME_r=random ./uname_unsetenv
INFO : env var "UNAME_s" set to "system"
: cleared env var "UNAME_s"
INFO : env var "UNAME_r" set to "random"
: cleared env var "UNAME_r"
INFO : env var "UNAME_m" set to "alpha64"
: cleared env var "UNAME_m"
-------------------------------------------------------------
system name = FreeBSD
node name = styx
release = 14.0-CURRENT
version = FreeBSD 14.0-CURRENT #0 main-n259756-6692670f58f9: Mon
Dec 19 16:48:48 UTC 2022 root@styx:/usr/obj/usr/src/amd64.amd64/sys/GENERIC
machine = amd64
-------------------------------------------------------------
styx$
Therefore the uname struct members are once again available to a given
process and we can determine inside an exec the system we are running
on from uname.
(2) Try to use putenv to clear the offending env vars
styx$ cat uname_putenv.c
/*
* uname_putenv.c Demonstrate that FreeBSD seems to allow env var
* values to override the uname(3) struct members.
* We may change the env var contents with putenv
* however putenv does not seem to work on the
* second call.
*
* Copyright (C) Dennis Clarke 2022
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* https://www.gnu.org/licenses/gpl-3.0.txt
*/
/*********************************************************************
* The Open Group Base Specifications Issue 6
* IEEE Std 1003.1, 2004 Edition
*
* An XSI-conforming application should ensure that the feature
* test macro _XOPEN_SOURCE is defined with the value 600 before
* inclusion of any header. This is needed to enable the
* functionality described in The _POSIX_C_SOURCE Feature Test
* Macro and in addition to enable the XSI extension.
*
*********************************************************************/
#define _XOPEN_SOURCE 600
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/utsname.h>
int main(int argc, char *argv[])
{
int j;
struct utsname uname_data;
char *env_var_value = NULL;
/* tricky stuff about UNAME(3) :
*
* These ENVIRONMENT variables override some uname struct members
*
* env name overrides
* --------------------------
* UNAME_s sysname
* UNAME_r release
* UNAME_v version
* UNAME_m machine
*
*/
char *env_var[] = {"UNAME_s","UNAME_r","UNAME_v","UNAME_m"};
/* These are likely not needed however the sources
* for putenv seem to check for the '=' character
* as well as the degenerate case where the submitted
* string is merely the '=' char. So these make it
* trivial to putenv an empty string. */
char *env_var_to_clear[] = {"UNAME_s=","UNAME_r=","UNAME_v=","UNAME_m="};
setlocale( LC_MESSAGES, "C" );
/* check for and then unset those env vars */
errno = 0;
for ( j=0; j<4 ; j++ ) {
env_var_value = getenv(env_var[j]);
if ( env_var_value != NULL) {
fprintf(stderr, "INFO : env var \"%s\" set to \"%s\"\n",
env_var[j], env_var_value);
if (putenv(env_var_to_clear[j]) < 0) {
fprintf(stderr, "FAIL : could not clear env \"%s\"\n",
env_var[j]);
perror("FAIL : ");
return EXIT_FAILURE;
} else {
fprintf(stderr, " : cleared env var \"%s\"\n", env_var[j]);
}
}
}
if ( uname( &uname_data ) < 0 ) {
fprintf(stderr,
"WARNING : Could not attain system uname data.\n" );
perror ("uname" );
} else {
printf("-------------------------------" );
printf("------------------------------\n" );
printf(" system name = %s\n", uname_data.sysname );
printf(" node name = %s\n", uname_data.nodename );
printf(" release = %s\n", uname_data.release );
printf(" version = %s\n", uname_data.version );
printf(" machine = %s\n", uname_data.machine );
printf ( "-------------------------------" );
printf ( "------------------------------" );
}
printf ("\n");
return EXIT_SUCCESS;
}
styx$
First we have the actual system :
styx$ uname -apKU
but why this styx 14.0-CURRENT FreeBSD 14.0-CURRENT #0
main-n259756-6692670f58f9: Mon Dec 19 16:48:48 UTC 2022
root@styx:/usr/obj/usr/src/amd64.amd64/sys/GENERIC amd64 amd64 1400075 1400075
styx$
However we can wreck havok with the uname members :
styx$ UNAME_s=system UNAME_m=alpha64 UNAME_r=random UNAME_v=NOTHING uname
-apKU
system styx random NOTHING alpha64 amd64 1400075 1400075
styx$
Worse, there seems to be no way to clear those values with putenv :
styx$
styx$ UNAME_s=system UNAME_m=alpha64 UNAME_r=random UNAME_v=NOTHING
./uname_putenv
INFO : env var "UNAME_s" set to "system"
: cleared env var "UNAME_s"
INFO : env var "UNAME_r" set to "random"
: cleared env var "UNAME_r"
INFO : env var "UNAME_v" set to "NOTHING"
: cleared env var "UNAME_v"
INFO : env var "UNAME_m" set to "alpha64"
: cleared env var "UNAME_m"
-------------------------------------------------------------
system name =
node name = styx
release =
version =
machine =
-------------------------------------------------------------
styx$
So the question would be, should putenv() allow the creation of these
env vars as zero length strings? I tested on a few other systems but
it seems only FreeBSD allows these UNAME_foo env vars to override the
uname struct members. Should putenv create zero length data for these
env vars?
Dennis Clarke
RISC-V/SPARC/PPC/ARM/CISC
UNIX and Linux spoken
GreyBeard and suspenders optional
--
You are receiving this mail because:
You are the assignee for the bug.