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:
Jeffrey Altman 2018-02-23 20:10:27 -05:00 committed by Benjamin Kaduk
parent d731d3c5bc
commit 8f1eba056f
9 changed files with 100 additions and 11 deletions

View File

@ -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

View File

@ -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>>] >>>

View File

@ -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));

View File

@ -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

View File

@ -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,

View File

@ -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;
}

View File

@ -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

View File

@ -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) {

View File

@ -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