Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164276624
D56680.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D56680.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D56680: automountd: crude attempt to drop privileges while executing map files
Attached
Detach File
Event Timeline
Log In to Comment