setaudit: Add an update mode

By default, setaudit(8) overwrites the whole audit session state.  For
the purpose of overwriting only a single field, e.g., the audit user,
this is inconvenient.  Add -U to accomodate this case: when specified,
setaudit(8) will first fetch the current session state block and then
will only overwrite those fields specified on the command line.

Reviewed by:	csjp
MFC after:	2 weeks
Sponsored by:	Modirum MDPay
Sponsored by:	Klara, Inc.
Differential Revision:	https://reviews.freebsd.org/D53672
This commit is contained in:
Mark Johnston 2025-11-17 16:45:29 +00:00
parent 551191e14e
commit 1238610a27
2 changed files with 39 additions and 11 deletions

View file

@ -28,7 +28,7 @@
.Nd "specify audit configurations on a process"
.Sh SYNOPSIS
.Nm
.Op Fl 46
.Op Fl 46U
.Op Fl a Ar auid
.Op Fl m Ar mask
.Op Fl s Ar source
@ -44,6 +44,16 @@ The following options are available:
Use IPv4.
.It Fl 6
Use IPv6.
.It Fl U
Update audit session state rather than overwriting it.
By default,
.Nm
will overwrite the entire audit session state using the specified
parameters.
If
.Fl U
is specified, only the parameters given on the command line will be
updated, leaving the rest unchanged.
.It Fl a Ar auid
Audit user ID or user name.
.It Fl m Ar mask

View file

@ -35,6 +35,7 @@
#include <err.h>
#include <netdb.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -44,7 +45,7 @@ static void
usage(char *prog)
{
(void)fprintf(stderr,
"usage: %s [-46] [-a auid] [-m mask] [-s source] [-p port] command ...\n",
"usage: %s [-46U] [-a auid] [-m mask] [-p port] [-s source] command ...\n",
prog);
exit(1);
}
@ -56,19 +57,21 @@ main(int argc, char *argv [])
struct sockaddr_in *sin;
struct addrinfo hints;
auditinfo_addr_t aia;
struct addrinfo *res;
struct passwd *pwd;
char *aflag, *mflag, *sflag, *prog;
dev_t term_port;
uint32_t term_type;
int ch, error;
bool Uflag;
aflag = mflag = sflag = NULL;
Uflag = false;
prog = argv[0];
bzero(&aia, sizeof(aia));
bzero(&hints, sizeof(hints));
aia.ai_termid.at_type = AU_IPv4;
term_type = AU_IPv4;
hints.ai_family = PF_UNSPEC;
while ((ch = getopt(argc, argv, "46a:m:p:s:")) != -1)
while ((ch = getopt(argc, argv, "46a:m:p:s:U")) != -1)
switch (ch) {
case '4':
hints.ai_family = PF_INET;
@ -83,11 +86,14 @@ main(int argc, char *argv [])
mflag = optarg;
break;
case 'p':
aia.ai_termid.at_port = htons(atoi(optarg));
term_port = htons(atoi(optarg));
break;
case 's':
sflag = optarg;
break;
case 'U':
Uflag = true;
break;
default:
usage(prog);
/* NOT REACHED */
@ -96,7 +102,14 @@ main(int argc, char *argv [])
argv += optind;
if (argc == 0)
usage(prog);
if (Uflag) {
if (getaudit_addr(&aia, sizeof(aia)) < 0)
err(1, "getaudit_addr");
}
if (aflag) {
struct passwd *pwd;
pwd = getpwnam(aflag);
if (pwd == NULL) {
char *r;
@ -112,6 +125,8 @@ main(int argc, char *argv [])
err(1, "getauditflagsbin");
}
if (sflag) {
struct addrinfo *res;
error = getaddrinfo(sflag, NULL, &hints, &res);
if (error)
errx(1, "%s", gai_strerror(error));
@ -121,20 +136,23 @@ main(int argc, char *argv [])
bcopy(&sin6->sin6_addr.s6_addr,
&aia.ai_termid.at_addr[0],
sizeof(struct in6_addr));
aia.ai_termid.at_type = AU_IPv6;
term_type = AU_IPv6;
break;
case PF_INET:
sin = (struct sockaddr_in *)(void *)res->ai_addr;
bcopy(&sin->sin_addr.s_addr,
&aia.ai_termid.at_addr[0],
sizeof(struct in_addr));
aia.ai_termid.at_type = AU_IPv4;
term_type = AU_IPv4;
break;
}
}
if (setaudit_addr(&aia, sizeof(aia)) < 0) {
err(1, "setaudit_addr");
if (!Uflag || sflag) {
aia.ai_termid.at_port = term_port;
aia.ai_termid.at_type = term_type;
}
if (setaudit_addr(&aia, sizeof(aia)) < 0)
err(1, "setaudit_addr");
(void)execvp(*argv, argv);
err(1, "%s", *argv);
}