From 0c729c229165bc32ef4f69ddb8bfed1aead94780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Mon, 18 Apr 2022 11:25:49 +0200 Subject: [PATCH] nfs: fix SMAP violation on write also rewrite the fix on read for consistency. should fix #17708 Change-Id: Ia75ed90ba427db7a7d96aff3457fbce61e857533 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5211 Tested-by: Commit checker robot Reviewed-by: waddlesplash --- src/add-ons/kernel/file_systems/nfs/Jamfile | 2 +- .../kernel/file_systems/nfs/XDRInPacket.c | 28 +++++++++------ .../kernel/file_systems/nfs/XDRInPacket.h | 5 ++- .../kernel/file_systems/nfs/XDROutPacket.c | 35 +++++++++++++------ .../kernel/file_systems/nfs/XDROutPacket.h | 6 ++-- .../kernel/file_systems/nfs/nfs_add_on.c | 13 ++++--- 6 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/add-ons/kernel/file_systems/nfs/Jamfile b/src/add-ons/kernel/file_systems/nfs/Jamfile index e6572ff361..a49853c928 100644 --- a/src/add-ons/kernel/file_systems/nfs/Jamfile +++ b/src/add-ons/kernel/file_systems/nfs/Jamfile @@ -1,6 +1,6 @@ SubDir HAIKU_TOP src add-ons kernel file_systems nfs ; -UsePrivateHeaders kernel ; +UsePrivateKernelHeaders ; #SubDirCcFlags -DTRACK_FILENAME ; diff --git a/src/add-ons/kernel/file_systems/nfs/XDRInPacket.c b/src/add-ons/kernel/file_systems/nfs/XDRInPacket.c index afa093f3bd..db81b477e6 100644 --- a/src/add-ons/kernel/file_systems/nfs/XDRInPacket.c +++ b/src/add-ons/kernel/file_systems/nfs/XDRInPacket.c @@ -1,9 +1,13 @@ #include "XDRInPacket.h" + #include #include + #include #include +#include + #include "nfs.h" extern void @@ -29,26 +33,28 @@ XDRInPacketGetInt32(struct XDRInPacket *packet) return val; } -extern int32 + +status_t XDRInPacketGetFixed(struct XDRInPacket *packet, void *buffer, size_t len) { - if (user_memcpy(buffer, &packet->fBuffer[packet->fOffset], len) - != B_OK) { - return NFSERR_IO; - } + if (!IS_USER_ADDRESS(buffer)) + memcpy(buffer, &packet->fBuffer[packet->fOffset], len); + else if (user_memcpy(buffer, &packet->fBuffer[packet->fOffset], len) != B_OK) + return B_BAD_ADDRESS; packet->fOffset += (len + 3) & ~3; - return NFS_OK; + return B_OK; } -extern size_t -XDRInPacketGetDynamic(struct XDRInPacket *packet, void *buffer) + +status_t +XDRInPacketGetDynamic(struct XDRInPacket *packet, void *buffer, size_t *len) { - size_t size=XDRInPacketGetInt32(packet); - XDRInPacketGetFixed(packet,buffer,size); - return size; + *len = XDRInPacketGetInt32(packet); + return XDRInPacketGetFixed(packet, buffer, *len); } + extern char * XDRInPacketGetString(struct XDRInPacket *packet) { diff --git a/src/add-ons/kernel/file_systems/nfs/XDRInPacket.h b/src/add-ons/kernel/file_systems/nfs/XDRInPacket.h index d59fc0757b..33b9774f58 100644 --- a/src/add-ons/kernel/file_systems/nfs/XDRInPacket.h +++ b/src/add-ons/kernel/file_systems/nfs/XDRInPacket.h @@ -13,9 +13,8 @@ struct XDRInPacket void XDRInPacketInit (struct XDRInPacket *packet); void XDRInPacketDestroy (struct XDRInPacket *packet); int32 XDRInPacketGetInt32 (struct XDRInPacket *packet); -int32 XDRInPacketGetFixed (struct XDRInPacket *packet, void *buffer, - size_t len); -size_t XDRInPacketGetDynamic (struct XDRInPacket *packet, void *buffer); +status_t XDRInPacketGetFixed (struct XDRInPacket *packet, void *buffer, size_t len); +status_t XDRInPacketGetDynamic (struct XDRInPacket *packet, void *buffer, size_t *_len); char *XDRInPacketGetString (struct XDRInPacket *packet); void XDRInPacketSetTo (struct XDRInPacket *packet, uint8 *buffer, size_t offset); diff --git a/src/add-ons/kernel/file_systems/nfs/XDROutPacket.c b/src/add-ons/kernel/file_systems/nfs/XDROutPacket.c index e99c5038d4..3fdf931bce 100644 --- a/src/add-ons/kernel/file_systems/nfs/XDROutPacket.c +++ b/src/add-ons/kernel/file_systems/nfs/XDROutPacket.c @@ -2,7 +2,12 @@ #include #include + #include +#include + +#include + extern const uint8 * XDROutPacketBuffer(struct XDROutPacket *packet) @@ -49,29 +54,37 @@ XDROutPacketAddInt32(struct XDROutPacket *packet, int32 val) packet->fLength+=4; } -extern void + +status_t XDROutPacketAddDynamic(struct XDROutPacket *packet, const void *data, size_t size) { - XDROutPacketAddInt32 (packet,size); - XDROutPacketAddFixed (packet,data,size); + XDROutPacketAddInt32(packet, size); + return XDROutPacketAddFixed(packet, data, size); } -extern void + +status_t XDROutPacketAddFixed(struct XDROutPacket *packet, const void *data, size_t size) { - size_t roundedSize=(size+3)&~3; - XDROutPacketGrow (packet,roundedSize); - memcpy (&packet->fBuffer[packet->fLength],data,size); - memset (&packet->fBuffer[packet->fLength+size],0,roundedSize-size); - packet->fLength+=roundedSize; + size_t roundedSize = (size + 3) & ~3; + XDROutPacketGrow(packet, roundedSize); + if (!IS_USER_ADDRESS(data)) + memcpy(&packet->fBuffer[packet->fLength], data, size); + else if (user_memcpy(&packet->fBuffer[packet->fLength], data, size) != B_OK) + return B_BAD_ADDRESS; + memset(&packet->fBuffer[packet->fLength + size], 0, roundedSize - size); + packet->fLength += roundedSize; + return B_OK; } -extern void + +status_t XDROutPacketAddString(struct XDROutPacket *packet, const char *string) { - XDROutPacketAddDynamic(packet,string,strlen(string)); + return XDROutPacketAddDynamic(packet, string, strlen(string)); } + extern void XDROutPacketAppend(struct XDROutPacket *me, const struct XDROutPacket *packet) { diff --git a/src/add-ons/kernel/file_systems/nfs/XDROutPacket.h b/src/add-ons/kernel/file_systems/nfs/XDROutPacket.h index 5ef1053fd4..7835b205d0 100644 --- a/src/add-ons/kernel/file_systems/nfs/XDROutPacket.h +++ b/src/add-ons/kernel/file_systems/nfs/XDROutPacket.h @@ -18,9 +18,9 @@ void XDROutPacketDestroy (struct XDROutPacket *packet); void XDROutPacketGrow (struct XDROutPacket *packet, size_t size); void XDROutPacketAddInt32 (struct XDROutPacket *packet, int32 val); -void XDROutPacketAddDynamic (struct XDROutPacket *packet, const void *data, size_t size); -void XDROutPacketAddFixed (struct XDROutPacket *packet, const void *data, size_t size); -void XDROutPacketAddString (struct XDROutPacket *packet, const char *string); +status_t XDROutPacketAddDynamic (struct XDROutPacket *packet, const void *data, size_t size); +status_t XDROutPacketAddFixed (struct XDROutPacket *packet, const void *data, size_t size); +status_t XDROutPacketAddString (struct XDROutPacket *packet, const char *string); void XDROutPacketAppend (struct XDROutPacket *me, const struct XDROutPacket *packet); const uint8 *XDROutPacketBuffer (struct XDROutPacket *packet); diff --git a/src/add-ons/kernel/file_systems/nfs/nfs_add_on.c b/src/add-ons/kernel/file_systems/nfs/nfs_add_on.c index 48d429f164..539abca69a 100644 --- a/src/add-ons/kernel/file_systems/nfs/nfs_add_on.c +++ b/src/add-ons/kernel/file_systems/nfs/nfs_add_on.c @@ -389,7 +389,8 @@ is_successful_reply(struct XDRInPacket *reply) } else { rpc_auth_flavor flavor = (rpc_auth_flavor)XDRInPacketGetInt32(reply); char body[400]; - size_t bodyLength = XDRInPacketGetDynamic(reply, body); + size_t bodyLength; + XDRInPacketGetDynamic(reply, body, &bodyLength); rpc_accept_stat acceptStat = (rpc_accept_stat)XDRInPacketGetInt32(reply); (void)flavor; @@ -1554,7 +1555,9 @@ fs_read(fs_volume *_volume, fs_vnode *_node, void *_cookie, off_t pos, get_nfs_attr(&reply, &st); cookie->st = st; - readbytes = XDRInPacketGetDynamic(&reply, buf); + status_t err = XDRInPacketGetDynamic(&reply, buf, &readbytes); + if (err != B_OK) + return err; buf = (char *)buf + readbytes; (*len) += readbytes; @@ -1605,7 +1608,9 @@ fs_write(fs_volume *_volume, fs_vnode *_node, void *_cookie, off_t pos, XDROutPacketAddInt32(&call, 0); XDROutPacketAddInt32(&call, pos + bytesWritten); XDROutPacketAddInt32(&call, 0); - XDROutPacketAddDynamic(&call, (const char *)buf + bytesWritten, count); + status_t err = XDROutPacketAddDynamic(&call, (const char *)buf + bytesWritten, count); + if (err != B_OK) + return err; replyBuf = send_rpc_call(ns, &ns->nfsAddr, NFS_PROGRAM, NFS_VERSION, NFSPROC_WRITE, &call); @@ -2309,7 +2314,7 @@ fs_readlink(fs_volume *_volume, fs_vnode *_node, char *buf, size_t *bufsize) return map_nfs_to_system_error(status); } - length = XDRInPacketGetDynamic(&reply, data); + XDRInPacketGetDynamic(&reply, data, &length); memcpy(buf, data, min_c(length, *bufsize)); *bufsize = length;