First Commit
[librecmc/package-feed.git] / libs / postgresql / patches / 900-pg_ctl-setuid.patch
1 Index: postgresql-9.5.4/src/bin/pg_ctl/pg_ctl.c
2 ===================================================================
3 --- postgresql-9.5.4.orig/src/bin/pg_ctl/pg_ctl.c
4 +++ postgresql-9.5.4/src/bin/pg_ctl/pg_ctl.c
5 @@ -95,6 +95,7 @@ static char *event_source = NULL;
6  static char *register_servicename = "PostgreSQL";              /* FIXME: + version ID? */
7  static char *register_username = NULL;
8  static char *register_password = NULL;
9 +static char *username = "";
10  static char *argv0 = NULL;
11  static bool allow_core_files = false;
12  static time_t start_time;
13 @@ -2114,6 +2115,9 @@ do_help(void)
14  #endif
15         printf(_("  -s, --silent           only print errors, no informational messages\n"));
16         printf(_("  -t, --timeout=SECS     seconds to wait when using -w option\n"));
17 +#if !defined(WIN32) && !defined(__CYGWIN__)
18 +       printf(_("  -U, --username=NAME    user name of account PostgreSQL server is running as\n"));
19 +#endif
20         printf(_("  -V, --version          output version information, then exit\n"));
21         printf(_("  -w                     wait until operation completes\n"));
22         printf(_("  -W                     do not wait until operation completes\n"));
23 @@ -2310,6 +2314,7 @@ main(int argc, char **argv)
24                 {"pgdata", required_argument, NULL, 'D'},
25                 {"silent", no_argument, NULL, 's'},
26                 {"timeout", required_argument, NULL, 't'},
27 +               {"username", required_argument, NULL, 'U'},
28                 {"core-files", no_argument, NULL, 'c'},
29                 {NULL, 0, NULL, 0}
30         };
31 @@ -2350,20 +2355,6 @@ main(int argc, char **argv)
32                 }
33         }
34  
35 -       /*
36 -        * Disallow running as root, to forestall any possible security holes.
37 -        */
38 -#ifndef WIN32
39 -       if (geteuid() == 0)
40 -       {
41 -               write_stderr(_("%s: cannot be run as root\n"
42 -                                          "Please log in (using, e.g., \"su\") as the "
43 -                                          "(unprivileged) user that will\n"
44 -                                          "own the server process.\n"),
45 -                                        progname);
46 -               exit(1);
47 -       }
48 -#endif
49  
50         env_wait = getenv("PGCTLTIMEOUT");
51         if (env_wait != NULL)
52 @@ -2449,11 +2440,15 @@ main(int argc, char **argv)
53                                         wait_seconds_arg = true;
54                                         break;
55                                 case 'U':
56 +#if defined(WIN32) || defined(__CYGWIN__)
57                                         if (strchr(optarg, '\\'))
58                                                 register_username = pg_strdup(optarg);
59                                         else
60                                                 /* Prepend .\ for local accounts */
61                                                 register_username = psprintf(".\\%s", optarg);
62 +#else
63 +                                       username = pg_strdup(optarg);
64 +#endif
65                                         break;
66                                 case 'w':
67                                         do_wait = true;
68 @@ -2535,6 +2530,41 @@ main(int argc, char **argv)
69                 exit(1);
70         }
71  
72 +       /*
73 +        * Disallow running as root, to forestall any possible security holes.
74 +        */
75 +#if !defined(WIN32) && !defined(__CYGWIN__)
76 +       if (geteuid() == 0)
77 +       {
78 +               struct passwd *p;
79 +               if (!username || !strlen(username)) {
80 +                       fprintf(stderr,
81 +                                       _("%s: when run as root, username needs to be provided\n"),
82 +                                       progname);
83 +                       exit(1);
84 +               }
85 +               p = getpwnam(username);
86 +               if (!p) {
87 +                       fprintf(stderr,
88 +                                       _("%s: invalid username: %s\n"),
89 +                                       progname, username);
90 +                       exit(1);
91 +               }
92 +               if (!p->pw_uid) {
93 +                       fprintf(stderr,
94 +                                       _("%s: user needs to be non-root\n"),
95 +                                       progname);
96 +                       exit(1);
97 +               }
98 +               if (setgid(p->pw_gid) || setuid(p->pw_uid)) {
99 +                       fprintf(stderr,
100 +                                       _("%s: failed to set user id %d: %d (%s)\n"),
101 +                                       progname, p->pw_uid, errno, strerror(errno));
102 +                       exit(1);
103 +               }
104 +       }
105 +#endif
106 +
107         /* Note we put any -D switch into the env var above */
108         pg_config = getenv("PGDATA");
109         if (pg_config)