Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/sh PR bin/56464



details:   https://anonhg.NetBSD.org/src/rev/7ef0c647a1e1
branches:  trunk
changeset: 1024485:7ef0c647a1e1
user:      kre <kre%NetBSD.org@localhost>
date:      Tue Oct 26 00:05:38 2021 +0000

description:
PR bin/56464

After almost 30 years, finally do the right thing and read $HOME/.profile
rather than .profile in the initial directory (it was that way in version
1.1 ...)   All other ash descendants seem to have fixed this long ago.

While here, copy a feature from FreeBSD which allows "set +p" (if a
shell run by a setuid process with the -p flag is privileged) to reset
the privileges.  Once done (the set +p) it cannot be undone (a later
set -p sets the 'p' flag, but that's all it does) - that just becomes a
one bit storage location.

We do this, as (also copying from FreeBSD, and because it is the right
thing to do) we don't run .profile in a privileged shell - FreeBSD run
/etc/suid_profile in that case (not a good name, it also applies to setgid
shells) but I see no real need for that, we run /etc/profile in any case,
anything that would go in /etc/suid_profile can just go in /etc/profile
instead (with suitable guards so the commands only run in priv'd shells).

One or two minor DEBUG mode changes (notably having priv'd shells identify
themselves in the DEBUG trace) and sh.1 changes with doc of the "set +p"
change, the effect that has on $PSc and a few other wording tweaks.

XXX pullup -9   (not -8, this isn't worth it for the short lifetime
that has left - if it took 28+ years for anyone to notice this, it
cannot be having all that much effect).

diffstat:

 bin/sh/main.c     |  37 ++++++++++++++++++++++++++----
 bin/sh/memalloc.c |  67 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 bin/sh/memalloc.h |   3 +-
 bin/sh/options.c  |  11 +++++++-
 bin/sh/sh.1       |  40 ++++++++++++++++++++++++++------
 bin/sh/shell.h    |   4 ++-
 6 files changed, 143 insertions(+), 19 deletions(-)

diffs (truncated from 387 to 300 lines):

diff -r c65e7ee1ca4a -r 7ef0c647a1e1 bin/sh/main.c
--- a/bin/sh/main.c     Mon Oct 25 21:33:24 2021 +0000
+++ b/bin/sh/main.c     Tue Oct 26 00:05:38 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: main.c,v 1.86 2021/09/15 18:29:45 kre Exp $    */
+/*     $NetBSD: main.c,v 1.87 2021/10/26 00:05:38 kre Exp $    */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -42,7 +42,7 @@
 #if 0
 static char sccsid[] = "@(#)main.c     8.7 (Berkeley) 7/19/95";
 #else
-__RCSID("$NetBSD: main.c,v 1.86 2021/09/15 18:29:45 kre Exp $");
+__RCSID("$NetBSD: main.c,v 1.87 2021/10/26 00:05:38 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -51,6 +51,7 @@
 #include <signal.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <locale.h>
 #include <fcntl.h>
@@ -86,6 +87,7 @@
 struct jmploc main_handler;
 int max_user_fd;
 long user_fd_limit;
+bool privileged;
 #if PROFILE
 short profile_buf[16384];
 extern int etext();
@@ -110,6 +112,7 @@
        uid_t uid;
        gid_t gid;
        sigset_t mask;
+       bool waspriv;
 
        /*
         * If we happen to be invoked with SIGCHLD ignored, we cannot
@@ -129,6 +132,8 @@
        uid = getuid();
        gid = getgid();
 
+       waspriv = privileged = (uid != geteuid()) || (gid != getegid());
+
        max_user_fd = fcntl(0, F_MAXFD);
        if (max_user_fd < 2)
                max_user_fd = 2;
@@ -194,6 +199,8 @@
        debug = 1;      /* this may be reset by procargs() later */
 #endif
        opentrace();
+       if (privileged)
+               trputs("Privileged ");
        trputs("Shell args:  ");  trargs(argv);
 #if DEBUG >= 3
        set_debug(((DEBUG)==3 ? "_@" : "++"), 1);
@@ -206,6 +213,7 @@
        setstackmark(&smark);
        procargs(argc, argv);
 
+#if 0  /* This now happens (indirectly) in the procargs() just above */
        /*
         * Limit bogus system(3) or popen(3) calls in setuid binaries,
         * by requiring the -p flag
@@ -216,18 +224,35 @@
                /* PS1 might need to be changed accordingly. */
                choose_ps1();
        }
+#else  /* except for this one little bit */
+       if (waspriv && !privileged)
+               choose_ps1();
+#endif
 
        if (argv[0] && argv[0][0] == '-') {
                state = 1;
                read_profile("/etc/profile");
  state1:
                state = 2;
-               read_profile(".profile");
+               if (!privileged) {
+                       char *profile;
+                       const char *home;
+
+                       home = lookupvar("HOME");
+                       if (home == NULL)
+                               home = nullstr;
+                       profile = ststrcat(NULL, home, "/.profile", NULL);
+                       read_profile(profile);
+                       stunalloc(profile);
+               }
+#if 0  /* FreeBSD does (effectively) ...*/
+               else
+                       read_profile("/etc/suid_profile");
+#endif
        }
  state2:
        state = 3;
-       if ((iflag || !posix) &&
-           getuid() == geteuid() && getgid() == getegid()) {
+       if ((iflag || !posix) && !privileged) {
                struct stackmark env_smark;
 
                setstackmark(&env_smark);
@@ -256,6 +281,8 @@
                    setsignal(sigs[i], 0);
        }
 
+       rststackmark(&smark);   /* this one is never popped */
+
        if (minusc)
                evalstring(minusc, sflag ? 0 : EV_EXIT);
 
diff -r c65e7ee1ca4a -r 7ef0c647a1e1 bin/sh/memalloc.c
--- a/bin/sh/memalloc.c Mon Oct 25 21:33:24 2021 +0000
+++ b/bin/sh/memalloc.c Tue Oct 26 00:05:38 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: memalloc.c,v 1.33 2019/02/09 03:35:55 kre Exp $        */
+/*     $NetBSD: memalloc.c,v 1.34 2021/10/26 00:05:38 kre Exp $        */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,10 +37,12 @@
 #if 0
 static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: memalloc.c,v 1.33 2019/02/09 03:35:55 kre Exp $");
+__RCSID("$NetBSD: memalloc.c,v 1.34 2021/10/26 00:05:38 kre Exp $");
 #endif
 #endif /* not lint */
 
+#include <limits.h>
+#include <stdarg.h>
 #include <stdlib.h>
 #include <unistd.h>
 
@@ -338,3 +340,64 @@
        stacknxt = s;
        sstrnleft = stacknleft - (p - s);
 }
+
+/*
+ * Save the concat of a sequence of strings in stack space
+ *
+ * The first arg (if not NULL) is a pointer to where the final string
+ * length will be returned.
+ *
+ * Remaining args are pointers to strings - sufficient space to hold
+ * the concat of the strings is allocated on the stack, the strings
+ * are copied into that space, and a pointer to its start is retured.
+ *
+ * Use stunalloc(string) (in proper sequence) to release the string
+ */
+char *
+ststrcat(size_t *lp, ...)
+{
+       va_list ap;
+       const char *arg;
+       size_t len, tlen = 0, alen[8];
+       char *str, *nxt;
+       unsigned int n;
+
+       n = 0;
+       va_start(ap, lp);
+       arg = va_arg(ap, const char *);
+       while (arg != NULL) {
+               len = strlen(arg);
+               if (n < sizeof(alen)/sizeof(alen[0]))
+                       alen[n++] = len;
+               tlen += len;
+               arg = va_arg(ap, const char *);
+       }
+       va_end(ap);
+
+       if (lp != NULL)
+               *lp = tlen;
+
+       if (tlen >= INT_MAX)
+               error("ststrcat() over length botch");
+       str = (char *)stalloc((int)tlen + 1);   /* 1 for \0 */
+
+       n = 0;
+       nxt = str;
+       va_start(ap, lp);
+       arg = va_arg(ap, const char *);
+       while (arg != NULL) {
+               if (n < sizeof(alen)/sizeof(alen[0]))
+                       len = alen[n++];
+               else
+                       len = strlen(arg);
+
+               scopy(arg, nxt);
+               nxt += len;
+
+               arg = va_arg(ap, const char *);
+       }
+       va_end(ap);
+
+       return str;
+}
+
diff -r c65e7ee1ca4a -r 7ef0c647a1e1 bin/sh/memalloc.h
--- a/bin/sh/memalloc.h Mon Oct 25 21:33:24 2021 +0000
+++ b/bin/sh/memalloc.h Tue Oct 26 00:05:38 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: memalloc.h,v 1.18 2018/08/22 20:08:54 kre Exp $        */
+/*     $NetBSD: memalloc.h,v 1.19 2021/10/26 00:05:38 kre Exp $        */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -61,6 +61,7 @@
 char *growstackstr(void);
 char *makestrspace(void);
 void ungrabstackstr(char *, char *);
+char *ststrcat(size_t *, ...);
 
 
 
diff -r c65e7ee1ca4a -r 7ef0c647a1e1 bin/sh/options.c
--- a/bin/sh/options.c  Mon Oct 25 21:33:24 2021 +0000
+++ b/bin/sh/options.c  Tue Oct 26 00:05:38 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: options.c,v 1.55 2020/02/05 14:56:25 kre Exp $ */
+/*     $NetBSD: options.c,v 1.56 2021/10/26 00:05:38 kre Exp $ */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)options.c  8.2 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: options.c,v 1.55 2020/02/05 14:56:25 kre Exp $");
+__RCSID("$NetBSD: options.c,v 1.56 2021/10/26 00:05:38 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -171,6 +171,13 @@
        histedit();
 #endif
        setjobctl(mflag);
+
+       if (privileged && !pflag) {
+               setuid(getuid());
+               setgid(getgid());
+               privileged = 0;
+               setvarsafe("PSc", (getuid() == 0 ? "#" : "$"), 0);
+       }
 }
 
 /*
diff -r c65e7ee1ca4a -r 7ef0c647a1e1 bin/sh/sh.1
--- a/bin/sh/sh.1       Mon Oct 25 21:33:24 2021 +0000
+++ b/bin/sh/sh.1       Tue Oct 26 00:05:38 2021 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: sh.1,v 1.234 2021/09/15 18:30:57 kre Exp $
+.\"    $NetBSD: sh.1,v 1.235 2021/10/26 00:05:38 kre Exp $
 .\" Copyright (c) 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
@@ -31,7 +31,7 @@
 .\"
 .\"    @(#)sh.1        8.6 (Berkeley) 5/4/95
 .\"
-.Dd September 11, 2021
+.Dd October 25, 2021
 .Dt SH 1
 .\" everything except c o and s (keep them ordered)
 .ds flags abCEeFfhIiLmnpquVvXx
@@ -317,7 +317,7 @@
 Enable the built-in emacs style
 command line editor (disables
 .Fl V
-if it has been set).
+if it had been set).
 (See the
 .Sx Command Line Editing
 section below.)
@@ -368,7 +368,7 @@
 commands to be executed by the function at the time of the definition.
 When off when a function is defined,
 the file system is searched for commands each time the function is invoked.
-(Not implemented.)
+(Obsolete and not implemented.)
 .It Fl I Em ignoreeof
 Ignore EOFs from input when interactive.
 (After a large number of consecutive EOFs the shell will exit anyway.)
@@ -404,18 +404,28 @@
 is written.
 .It Fl p Em nopriv
 Do not attempt to reset effective UID if it does not match UID.
+The same applies to effective and real GIDs.
 This is not set by default to help avoid incorrect usage by setuid
 root programs via
 .Xr system 3
 or
 .Xr popen 3 .
+This option is effective only when set on the command line,



Home | Main Index | Thread Index | Old Index