Page MenuHomeFreeBSD

D56680.diff
No OneTemporary

D56680.diff

diff --git a/usr.sbin/autofs/auto_master.5 b/usr.sbin/autofs/auto_master.5
--- a/usr.sbin/autofs/auto_master.5
+++ b/usr.sbin/autofs/auto_master.5
@@ -27,7 +27,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 27, 2023
+.Dd April 27, 2026
.Dt AUTO_MASTER 5
.Os
.Sh NAME
@@ -293,6 +293,12 @@
a command line argument.
Output from the executable is expected to be the entry for that key,
not including the key itself.
+.Pp
+.Xr automountd 8
+will drop privileges to execute the map file by default, but can be instructed
+to run it as root instead with the
+.Fl S
+option.
.Sh INDIRECT VERSUS DIRECT MAPS
Indirect maps are referred to in
.Nm
@@ -353,6 +359,12 @@
.Pa /etc/autofs/include_ldap .
It can be symlinked to
.Pa /etc/autofs/include .
+.Pp
+As described above in
+.Sx EXECUTABLE MAPS ,
+the
+.Xr automountd 8
+will drop privileges to execute the include script unless instructed otherwise.
.Sh FILES
.Bl -tag -width ".Pa /etc/auto_master" -compact
.It Pa /etc/auto_master
diff --git a/usr.sbin/autofs/automountd.8 b/usr.sbin/autofs/automountd.8
--- a/usr.sbin/autofs/automountd.8
+++ b/usr.sbin/autofs/automountd.8
@@ -27,7 +27,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd March 10, 2015
+.Dd April 27, 2026
.Dt AUTOMOUNTD 8
.Os
.Sh NAME
@@ -36,6 +36,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl D Ar name=value
+.Op Fl S
.Op Fl i
.Op Fl m Ar maxproc
.Op Fl o Ar options
@@ -60,6 +61,10 @@
.Bl -tag -width "-m maxproc"
.It Fl D
Define a variable.
+.It Fl S
+Do not drop privileges when executing scripts while parsing
+.Xr auto_master 5
+configuration.
.It Fl i
For indirect mounts, only create subdirectories if there are no wildcard
entries.
diff --git a/usr.sbin/autofs/automountd.c b/usr.sbin/autofs/automountd.c
--- a/usr.sbin/autofs/automountd.c
+++ b/usr.sbin/autofs/automountd.c
@@ -169,7 +169,7 @@
static void
handle_request(const struct autofs_daemon_request *adr, char *cmdline_options,
- bool incomplete_hierarchy)
+ bool incomplete_hierarchy, bool do_setuid)
{
const char *map;
struct node *root, *parent, *node;
@@ -224,7 +224,7 @@
* needs to be done for maps with wildcard entries, but also
* for special and executable maps.
*/
- parse_map(parent, map, key, &wildcards);
+ parse_map(parent, map, key, &wildcards, do_setuid);
if (!wildcards)
wildcards = node_has_wildcards(parent);
if (wildcards)
@@ -344,7 +344,7 @@
}
}
- f = auto_popen("mount", "-t", fstype, "-o", options,
+ f = auto_popen(false, "mount", "-t", fstype, "-o", options,
node->n_location, adr->adr_path, NULL);
assert(f != NULL);
error = auto_pclose(f);
@@ -424,7 +424,7 @@
{
fprintf(stderr, "usage: automountd [-D name=value][-m maxproc]"
- "[-o opts][-Tidv]\n");
+ "[-o opts][-STidv]\n");
exit(1);
}
@@ -438,14 +438,18 @@
struct autofs_daemon_request request;
int ch, debug = 0, error, maxproc = 30, retval, saved_errno;
bool dont_daemonize = false, incomplete_hierarchy = false;
+ bool do_setuid = true;
defined_init();
- while ((ch = getopt(argc, argv, "D:Tdim:o:v")) != -1) {
+ while ((ch = getopt(argc, argv, "D:STdim:o:v")) != -1) {
switch (ch) {
case 'D':
defined_parse_and_add(optarg);
break;
+ case 'S':
+ do_setuid = false;
+ break;
case 'T':
/*
* For compatibility with other implementations,
@@ -556,7 +560,8 @@
}
pidfile_close(pidfh);
- handle_request(&request, options, incomplete_hierarchy);
+ handle_request(&request, options, incomplete_hierarchy,
+ do_setuid);
}
pidfile_close(pidfh);
diff --git a/usr.sbin/autofs/common.h b/usr.sbin/autofs/common.h
--- a/usr.sbin/autofs/common.h
+++ b/usr.sbin/autofs/common.h
@@ -89,7 +89,7 @@
void node_print(const struct node *n, const char *cmdline_options);
void parse_master(struct node *root, const char *path);
void parse_map(struct node *parent, const char *map, const char *args,
- bool *wildcards);
+ bool *wildcards, bool do_setuid);
char *defined_expand(const char *string);
void defined_init(void);
void defined_parse_and_add(char *def);
@@ -100,7 +100,7 @@
int main_automountd(int argc, char **argv);
int main_autounmountd(int argc, char **argv);
-FILE *auto_popen(const char *argv0, ...);
+FILE *auto_popen(bool do_setuid, const char *argv0, ...);
int auto_pclose(FILE *iop);
/*
diff --git a/usr.sbin/autofs/common.c b/usr.sbin/autofs/common.c
--- a/usr.sbin/autofs/common.c
+++ b/usr.sbin/autofs/common.c
@@ -284,7 +284,7 @@
}
static void
-node_expand_includes(struct node *root, bool is_master)
+node_expand_includes(struct node *root, bool is_master, bool do_setuid)
{
struct node *n, *n2, *tmp, *tmp2, *tmproot;
int error;
@@ -302,7 +302,8 @@
/*
* "+1" to skip leading "+".
*/
- yyin = auto_popen(AUTO_INCLUDE_PATH, n->n_key + 1, NULL);
+ yyin = auto_popen(do_setuid, AUTO_INCLUDE_PATH, n->n_key + 1,
+ NULL);
assert(yyin != NULL);
tmproot = node_new_root();
@@ -499,7 +500,7 @@
}
static void
-node_expand_maps(struct node *n, bool indirect)
+node_expand_maps(struct node *n, bool indirect, bool do_setuid)
{
struct node *child, *tmp;
@@ -526,22 +527,22 @@
log_debugx("map \"%s\" is a direct map, parsing",
child->n_map);
}
- parse_map(child, child->n_map, NULL, NULL);
+ parse_map(child, child->n_map, NULL, NULL, do_setuid);
}
}
static void
-node_expand_direct_maps(struct node *n)
+node_expand_direct_maps(struct node *n, bool do_setuid)
{
- node_expand_maps(n, false);
+ node_expand_maps(n, false, do_setuid);
}
void
node_expand_indirect_maps(struct node *n)
{
- node_expand_maps(n, true);
+ node_expand_maps(n, true, false);
}
static char *
@@ -953,7 +954,8 @@
* Parse a special map, e.g. "-hosts".
*/
static void
-parse_special_map(struct node *parent, const char *map, const char *key)
+parse_special_map(struct node *parent, const char *map, const char *key,
+ bool do_setuid)
{
char *path;
int error, ret;
@@ -967,7 +969,7 @@
if (ret < 0)
log_err(1, "asprintf");
- yyin = auto_popen(path, key, NULL);
+ yyin = auto_popen(do_setuid, path, key, NULL);
assert(yyin != NULL);
if (key == NULL) {
@@ -981,8 +983,8 @@
if (error != 0)
log_errx(1, "failed to handle special map \"%s\"", map);
- node_expand_includes(parent, false);
- node_expand_direct_maps(parent);
+ node_expand_includes(parent, false, do_setuid);
+ node_expand_direct_maps(parent, do_setuid);
free(path);
}
@@ -996,7 +998,7 @@
* argument, instead of key.
*/
static void
-parse_included_map(struct node *parent, const char *map)
+parse_included_map(struct node *parent, const char *map, bool do_setuid)
{
int error;
@@ -1009,7 +1011,7 @@
" %s does not exist", AUTO_INCLUDE_PATH);
}
- yyin = auto_popen(AUTO_INCLUDE_PATH, map, NULL);
+ yyin = auto_popen(do_setuid, AUTO_INCLUDE_PATH, map, NULL);
assert(yyin != NULL);
parse_map_yyin(parent, map, NULL);
@@ -1019,13 +1021,13 @@
if (error != 0)
log_errx(1, "failed to handle remote map \"%s\"", map);
- node_expand_includes(parent, false);
- node_expand_direct_maps(parent);
+ node_expand_includes(parent, false, do_setuid);
+ node_expand_direct_maps(parent, do_setuid);
}
void
parse_map(struct node *parent, const char *map, const char *key,
- bool *wildcards)
+ bool *wildcards, bool do_setuid)
{
char *path = NULL;
int error, ret;
@@ -1042,7 +1044,7 @@
if (map[0] == '-') {
if (wildcards != NULL)
*wildcards = true;
- return (parse_special_map(parent, map, key));
+ return (parse_special_map(parent, map, key, do_setuid));
}
if (map[0] == '/') {
@@ -1061,7 +1063,7 @@
if (error != 0) {
log_debugx("map file \"%s\" does not exist; falling "
"back to directory services", path);
- return (parse_included_map(parent, map));
+ return (parse_included_map(parent, map, do_setuid));
}
}
@@ -1074,9 +1076,9 @@
*wildcards = true;
if (key != NULL) {
- yyin = auto_popen(path, key, NULL);
+ yyin = auto_popen(do_setuid, path, key, NULL);
} else {
- yyin = auto_popen(path, NULL);
+ yyin = auto_popen(do_setuid, path, NULL);
}
assert(yyin != NULL);
} else {
@@ -1104,8 +1106,8 @@
log_debugx("done parsing map \"%s\"", map);
- node_expand_includes(parent, false);
- node_expand_direct_maps(parent);
+ node_expand_includes(parent, false, do_setuid);
+ node_expand_direct_maps(parent, do_setuid);
}
static void
@@ -1167,8 +1169,8 @@
log_debugx("done parsing \"%s\"", master);
- node_expand_includes(root, true);
- node_expand_direct_maps(root);
+ node_expand_includes(root, true, false);
+ node_expand_direct_maps(root, false);
}
/*
@@ -1210,7 +1212,7 @@
{
FILE *f;
- f = auto_popen("rpc.umntall", "-k", NULL);
+ f = auto_popen(false, "rpc.umntall", "-k", NULL);
assert(f != NULL);
auto_pclose(f);
}
diff --git a/usr.sbin/autofs/popen.c b/usr.sbin/autofs/popen.c
--- a/usr.sbin/autofs/popen.c
+++ b/usr.sbin/autofs/popen.c
@@ -39,11 +39,13 @@
*/
#include <sys/param.h>
+#include <sys/conf.h>
#include <sys/queue.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
+#include <pwd.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
@@ -71,14 +73,28 @@
* Error handling is built in - if it returns, then it succeeded.
*/
FILE *
-auto_popen(const char *argv0, ...)
+auto_popen(bool do_setuid, const char *argv0, ...)
{
+ static struct passwd *pwd;
va_list ap;
struct pid *cur, *p;
pid_t pid;
int error, i, nullfd, outfds[2];
char *arg, *argv[ARGV_LEN], *command;
+ if (do_setuid && pwd == NULL) {
+ /* Cache on first access. */
+ errno = 0;
+ pwd = getpwuid(UID_AUTOMOUNT);
+ if (pwd == NULL) {
+ if (errno == 0)
+ errno = ENOENT;
+ log_err(1,
+ "failed to lookup passwd entry for _automount for %s",
+ argv0);
+ }
+ }
+
nullfd = open(_PATH_DEVNULL, O_RDWR, 0);
if (nullfd < 0)
log_err(1, "cannot open %s", _PATH_DEVNULL);
@@ -121,6 +137,26 @@
close(outfds[0]);
close(outfds[1]);
+ if (do_setuid) {
+ if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
+ log_err(1,
+ "failed to drop supplementary groups for %s",
+ argv[0]);
+ }
+
+ if (setgid(pwd->pw_gid) == -1) {
+ log_err(1,
+ "failed to setgid unprivileged for %s",
+ argv[0]);
+ }
+
+ if (setuid(pwd->pw_uid) == -1) {
+ log_err(1,
+ "failed to setuid unprivileged for %s",
+ argv[0]);
+ }
+ }
+
SLIST_FOREACH(p, &pidlist, next)
close(fileno(p->outfp));
execvp(argv[0], argv);

File Metadata

Mime Type
text/plain
Expires
Fri, Jul 31, 7:31 AM (14 h, 59 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35776172
Default Alt Text
D56680.diff (10 KB)

Event Timeline