mirror of
https://git.openafs.org/openafs.git
synced 2025-01-18 15:00:12 +00:00
CVE-2018-7168 RXAFS_StoreACL deprecate 134 introduce 164
There exist in the wild AFS3 clients that improperly construct access control lists which are then stored to directories via RXAFS_StoreACL (opcode 134). These clients add negative access control entries (if any) to the normal rights list. As there is no method by which a fileserver can determine that the ACL is improperly constructed, the only method to defend the storage of broken ACLs is to identify clients that are known to properly construct ACLs by introducing a new RXAFS_StoreACL opcode (164). This change: * Renames RXAFS opcode 134 to RXAFS_OldStoreACL * Introduces RXAFS opcode 164 as RXAFS_StoreACL * Implements SRXAFS_OldStoreACL and SRXAFS_StoreACL in the fileserver via a common_StoreACL() function that accepts the executed opcode as input. * To avoid breaking changes in stable release branches, SRXAFS_OldStoreACL will still be allowed by default, with an option to cause it to be failed by default with error EPERM/UAEPERM. A follow-up commit will cause SRXAFS_OldStoreACL to fail by default on the master branch. * When opcode 134 is called, the a FileLog entry will be generated at log level 0 instead of 1 and the entry will contain the string "CVE-2018-7168". * Modifies the format of the ACL logged to the FileLog and the audit stream. Previously the AFSOpaque format was used directly. The problem with this format is that it uses newlines as the ACE separator. Since the FileLog and file audit log is intended to be one line per log entry, the newlines break the file formats. This change replaces the newlines with spaces for display purposes unless the process is unable to allocate the additional memory. * Introduces a new fileserver command line switch -cve-2018-7168-enforce which when specified causes SRXAFS_OldStoreACL RPCs to be failed. [kaduk@mit.edu: switch en/disable-by-default behavior and fix argument parsing] Change-Id: Ic92ef45314d75fbc2b8ff574223fab2d398a1d60 FIXES: 134485 Reviewed-on: https://gerrit.openafs.org/12942 Reviewed-by: Jeffrey Altman <jaltman@auristor.com> Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
This commit is contained in:
parent
d731d3c5bc
commit
8f1eba056f
@ -320,6 +320,13 @@ restarted. This option is provided for compatibility with older versions.
|
||||
Offer the SANEACLS capability for the fileserver. This option is
|
||||
currently unimplemented.
|
||||
|
||||
-item B<-cve-2018-7168-enforce>
|
||||
|
||||
To address L<CVE-2018-7168|https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-7168>
|
||||
disable fileserver opcode RXAFS_StoreACL (134). This opcode was replaced
|
||||
with RXAFS_StoreACL (164). The opcode 164 is always available; this option serves
|
||||
only to disable the old opcode 134, for which client intent is unreliable.
|
||||
|
||||
=item B<-help>
|
||||
|
||||
Prints the online help for this command. All other valid options are
|
||||
|
@ -40,6 +40,7 @@ B<fileserver>
|
||||
S<<< [B<-mrafslogs>] >>>
|
||||
S<<< [B<-transarc-logs>] >>>
|
||||
S<<< [B<-saneacls>] >>>
|
||||
S<<< [B<-cve-2018-7168-enforce>] >>>
|
||||
S<<< [B<-help>] >>>
|
||||
S<<< [B<-vhandle-setaside> <I<fds reserved for non-cache io>>] >>>
|
||||
S<<< [B<-vhandle-max-cachesize> <I<max open files>>] >>>
|
||||
|
@ -538,6 +538,8 @@ cm_IoctlSetACL(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp,
|
||||
|
||||
rxconnp = cm_GetRxConn(connp);
|
||||
code = RXAFS_StoreACL(rxconnp, &fid, &acl, &fileStatus, &volSync);
|
||||
if (code == RXGEN_OPCODE)
|
||||
code = RXAFS_OldStoreACL(rxconnp, &fid, &acl, &fileStatus, &volSync);
|
||||
rx_PutConnection(rxconnp);
|
||||
|
||||
} while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 1, &fileStatus, &volSync, NULL, NULL, code));
|
||||
|
@ -1457,9 +1457,12 @@ DECL_PIOCTL(PSetAcl)
|
||||
if (tconn) {
|
||||
XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
|
||||
RX_AFS_GUNLOCK();
|
||||
code =
|
||||
RXAFS_StoreACL(rxconn, (struct AFSFid *)&avc->f.fid.Fid,
|
||||
&acl, &OutStatus, &tsync);
|
||||
code = RXAFS_StoreACL(rxconn, (struct AFSFid *)&avc->f.fid.Fid,
|
||||
&acl, &OutStatus, &tsync);
|
||||
if (code == RXGEN_OPCODE)
|
||||
code = RXAFS_OldStoreACL(rxconn,
|
||||
(struct AFSFid *)&avc->f.fid.Fid,
|
||||
&acl, &OutStatus, &tsync);
|
||||
RX_AFS_GLOCK();
|
||||
XSTATS_END_TIME;
|
||||
} else
|
||||
|
@ -310,7 +310,8 @@ StoreData(
|
||||
AFSVolSync *Sync
|
||||
) split = 133;
|
||||
|
||||
StoreACL(
|
||||
/* Deprecated - CVE-2018-7168 */
|
||||
OldStoreACL(
|
||||
IN AFSFid *Fid,
|
||||
AFSOpaque *AccessList,
|
||||
OUT AFSFetchStatus *OutStatus,
|
||||
@ -520,6 +521,13 @@ DFSSymlink(
|
||||
AFSVolSync *Sync
|
||||
) = 163;
|
||||
|
||||
StoreACL(
|
||||
IN AFSFid *Fid,
|
||||
AFSOpaque *AccessList,
|
||||
OUT AFSFetchStatus *OutStatus,
|
||||
AFSVolSync *Sync
|
||||
) = 164;
|
||||
|
||||
FsCmd(
|
||||
IN AFSFid *Fid,
|
||||
IN struct FsCmdInputs *Inputs,
|
||||
|
@ -94,6 +94,9 @@ afscp_StoreACL(const struct afscp_venusfid *dir, struct AFSOpaque *acl)
|
||||
if (server && server->naddrs > 0) {
|
||||
for (j = 0; j < server->naddrs; j++) {
|
||||
code = RXAFS_StoreACL(server->conns[j], &df, acl, &dfst, &vs);
|
||||
if (code == RXGEN_OPCODE)
|
||||
code = RXAFS_OldStoreACL(server->conns[j], &df, acl,
|
||||
&dfst, &vs);
|
||||
if (code >= 0)
|
||||
break;
|
||||
}
|
||||
|
@ -3053,8 +3053,28 @@ SRXAFS_StoreData64(struct rx_call * acall, struct AFSFid * Fid,
|
||||
return code;
|
||||
}
|
||||
|
||||
afs_int32
|
||||
SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
|
||||
static char *
|
||||
printableACL(struct AFSOpaque *AccessList)
|
||||
{
|
||||
char *s;
|
||||
size_t i;
|
||||
|
||||
s = calloc(1, AccessList->AFSOpaque_len + 1);
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < AccessList->AFSOpaque_len; i++) {
|
||||
if (AccessList->AFSOpaque_val[i] == '\n')
|
||||
s[i] = ' ';
|
||||
else
|
||||
s[i] = AccessList->AFSOpaque_val[i];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static afs_int32
|
||||
common_StoreACL(afs_uint64 opcode,
|
||||
struct rx_call * acall, struct AFSFid * Fid,
|
||||
struct AFSOpaque * AccessList,
|
||||
struct AFSFetchStatus * OutStatus, struct AFSVolSync * Sync)
|
||||
{
|
||||
@ -3070,6 +3090,8 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
|
||||
struct client *t_client = NULL; /* tmp ptr to client data */
|
||||
struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
|
||||
struct fsstats fsstats;
|
||||
char *displayACL = NULL;
|
||||
int newOpcode = (opcode == opcode_RXAFS_StoreACL);
|
||||
|
||||
fsstats_StartOp(&fsstats, FS_STATS_RPCIDX_STOREACL);
|
||||
|
||||
@ -3079,9 +3101,12 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
|
||||
/* Get ptr to client data for user Id for logging */
|
||||
t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
|
||||
logHostAddr.s_addr = rxr_HostOf(tcon);
|
||||
ViceLog(1,
|
||||
("SAFS_StoreACL, Fid = %u.%u.%u, ACL=%s, Host %s:%d, Id %d\n",
|
||||
Fid->Volume, Fid->Vnode, Fid->Unique, AccessList->AFSOpaque_val,
|
||||
displayACL = printableACL(AccessList);
|
||||
ViceLog(newOpcode ? 1 : 0,
|
||||
("SAFS_StoreACL%s, Fid = %u.%u.%u, ACL=%s, Host %s:%d, Id %d\n",
|
||||
newOpcode ? "" : " CVE-2018-7168",
|
||||
Fid->Volume, Fid->Vnode, Fid->Unique,
|
||||
displayACL == NULL ? AccessList->AFSOpaque_val : displayACL,
|
||||
inet_ntoa(logHostAddr), ntohs(rxr_PortOf(tcon)), t_client->z.ViceId));
|
||||
FS_LOCK;
|
||||
AFSCallStats.StoreACL++, AFSCallStats.TotalCalls++;
|
||||
@ -3109,6 +3134,12 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
|
||||
goto Bad_StoreACL;
|
||||
}
|
||||
|
||||
if (opcode == opcode_RXAFS_OldStoreACL && !enable_old_store_acl) {
|
||||
/* CVE-2018-7168 - administratively prohibited */
|
||||
errorCode = EPERM;
|
||||
goto Bad_StoreACL;
|
||||
}
|
||||
|
||||
/* Build and store the new Access List for the dir */
|
||||
if ((errorCode = RXStore_AccessList(targetptr, AccessList))) {
|
||||
goto Bad_StoreACL;
|
||||
@ -3130,18 +3161,43 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
|
||||
/* Update and store volume/vnode and parent vnodes back */
|
||||
PutVolumePackage(acall, parentwhentargetnotdir, targetptr, (Vnode *) 0,
|
||||
volptr, &client);
|
||||
ViceLog(2, ("SAFS_StoreACL returns %d\n", errorCode));
|
||||
|
||||
ViceLog(2, ("%s returns %d\n",
|
||||
opcode == opcode_RXAFS_StoreACL ? "SAFS_StoreACL"
|
||||
: "SAFS_OldStoreACL",
|
||||
errorCode));
|
||||
errorCode = CallPostamble(tcon, errorCode, thost);
|
||||
|
||||
fsstats_FinishOp(&fsstats, errorCode);
|
||||
|
||||
osi_auditU(acall, StoreACLEvent, errorCode,
|
||||
AUD_ID, t_client ? t_client->z.ViceId : 0,
|
||||
AUD_FID, Fid, AUD_ACL, AccessList->AFSOpaque_val, AUD_END);
|
||||
AUD_FID, Fid, AUD_ACL,
|
||||
displayACL == NULL ? AccessList->AFSOpaque_val : displayACL,
|
||||
AUD_END);
|
||||
free(displayACL);
|
||||
return errorCode;
|
||||
|
||||
} /*SRXAFS_StoreACL */
|
||||
|
||||
/* SRXAFS_OldStoreACL (Deprecated - CVE-2018-7168 */
|
||||
afs_int32
|
||||
SRXAFS_OldStoreACL(struct rx_call *acall, struct AFSFid *Fid,
|
||||
struct AFSOpaque *AccessList,
|
||||
struct AFSFetchStatus *OutStatus, struct AFSVolSync *Sync)
|
||||
{
|
||||
return common_StoreACL(opcode_RXAFS_OldStoreACL, acall, Fid, AccessList,
|
||||
OutStatus, Sync);
|
||||
}
|
||||
|
||||
afs_int32
|
||||
SRXAFS_StoreACL(struct rx_call *acall, struct AFSFid *Fid,
|
||||
struct AFSOpaque *AccessList,
|
||||
struct AFSFetchStatus *OutStatus, struct AFSVolSync *Sync)
|
||||
{
|
||||
return common_StoreACL(opcode_RXAFS_StoreACL, acall, Fid, AccessList,
|
||||
OutStatus, Sync);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: This routine is called exclusively from SRXAFS_StoreStatus(), and
|
||||
|
@ -163,6 +163,7 @@ int abort_threshold = 10;
|
||||
int udpBufSize = 0; /* UDP buffer size for receive */
|
||||
int sendBufSize = 16384; /* send buffer size */
|
||||
int saneacls = 0; /* Sane ACLs Flag */
|
||||
int enable_old_store_acl = 1; /* -cve-2018-7168-enforce */
|
||||
static int unsafe_attach = 0; /* avoid inUse check on vol attach? */
|
||||
static int offline_timeout = -1; /* -offline-timeout option */
|
||||
static int offline_shutdown_timeout = -1; /* -offline-shutdown-timeout option */
|
||||
@ -893,6 +894,7 @@ enum optionsList {
|
||||
OPT_readonly,
|
||||
OPT_adminwrite,
|
||||
OPT_saneacls,
|
||||
OPT_cve_2018_7168,
|
||||
OPT_buffers,
|
||||
OPT_callbacks,
|
||||
OPT_vcsize,
|
||||
@ -991,6 +993,8 @@ ParseArgs(int argc, char *argv[])
|
||||
"from system:administrators");
|
||||
cmd_AddParmAtOffset(opts, OPT_saneacls, "-saneacls", CMD_FLAG,
|
||||
CMD_OPTIONAL, "set the saneacls capability bit");
|
||||
cmd_AddParmAtOffset(opts, OPT_cve_2018_7168, "-cve-2018-7168-enforce", CMD_FLAG,
|
||||
CMD_OPTIONAL, "disable (unreliable) old store acls rpc (opcode 134)");
|
||||
|
||||
cmd_AddParmAtOffset(opts, OPT_buffers, "-b", CMD_SINGLE,
|
||||
CMD_OPTIONAL, "buffers");
|
||||
@ -1192,6 +1196,10 @@ ParseArgs(int argc, char *argv[])
|
||||
cmd_OptionAsFlag(opts, OPT_readonly, &readonlyServer);
|
||||
cmd_OptionAsFlag(opts, OPT_adminwrite, &adminwriteServer);
|
||||
cmd_OptionAsFlag(opts, OPT_saneacls, &saneacls);
|
||||
optval = 0;
|
||||
cmd_OptionAsFlag(opts, OPT_cve_2018_7168, &optval);
|
||||
if (optval != 0)
|
||||
enable_old_store_acl = 0;
|
||||
cmd_OptionAsInt(opts, OPT_buffers, &buffs);
|
||||
|
||||
if (cmd_OptionAsInt(opts, OPT_callbacks, &numberofcbs) == 0) {
|
||||
|
@ -182,6 +182,7 @@ struct AFSStatistics {
|
||||
|
||||
extern int busyonrst;
|
||||
extern int saneacls;
|
||||
extern int enable_old_store_acl;
|
||||
|
||||
#define RESTART_ORDINARY 1
|
||||
#define RESTART_FAST 2
|
||||
|
Loading…
Reference in New Issue
Block a user