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 <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Jérôme Duval
2022-04-18 14:48:35 +00:00
committed by waddlesplash
parent 9501bd1241
commit 0c729c2291
6 changed files with 56 additions and 33 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
SubDir HAIKU_TOP src add-ons kernel file_systems nfs ; SubDir HAIKU_TOP src add-ons kernel file_systems nfs ;
UsePrivateHeaders kernel ; UsePrivateKernelHeaders ;
#SubDirCcFlags -DTRACK_FILENAME ; #SubDirCcFlags -DTRACK_FILENAME ;
@@ -1,9 +1,13 @@
#include "XDRInPacket.h" #include "XDRInPacket.h"
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
#include <ByteOrder.h> #include <ByteOrder.h>
#include <KernelExport.h> #include <KernelExport.h>
#include <kernel.h>
#include "nfs.h" #include "nfs.h"
extern void extern void
@@ -29,26 +33,28 @@ XDRInPacketGetInt32(struct XDRInPacket *packet)
return val; return val;
} }
extern int32
status_t
XDRInPacketGetFixed(struct XDRInPacket *packet, void *buffer, size_t len) XDRInPacketGetFixed(struct XDRInPacket *packet, void *buffer, size_t len)
{ {
if (user_memcpy(buffer, &packet->fBuffer[packet->fOffset], len) if (!IS_USER_ADDRESS(buffer))
!= B_OK) { memcpy(buffer, &packet->fBuffer[packet->fOffset], len);
return NFSERR_IO; else if (user_memcpy(buffer, &packet->fBuffer[packet->fOffset], len) != B_OK)
} return B_BAD_ADDRESS;
packet->fOffset += (len + 3) & ~3; 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); *len = XDRInPacketGetInt32(packet);
XDRInPacketGetFixed(packet,buffer,size); return XDRInPacketGetFixed(packet, buffer, *len);
return size;
} }
extern char * extern char *
XDRInPacketGetString(struct XDRInPacket *packet) XDRInPacketGetString(struct XDRInPacket *packet)
{ {
@@ -13,9 +13,8 @@ struct XDRInPacket
void XDRInPacketInit (struct XDRInPacket *packet); void XDRInPacketInit (struct XDRInPacket *packet);
void XDRInPacketDestroy (struct XDRInPacket *packet); void XDRInPacketDestroy (struct XDRInPacket *packet);
int32 XDRInPacketGetInt32 (struct XDRInPacket *packet); int32 XDRInPacketGetInt32 (struct XDRInPacket *packet);
int32 XDRInPacketGetFixed (struct XDRInPacket *packet, void *buffer, status_t XDRInPacketGetFixed (struct XDRInPacket *packet, void *buffer, size_t len);
size_t len); status_t XDRInPacketGetDynamic (struct XDRInPacket *packet, void *buffer, size_t *_len);
size_t XDRInPacketGetDynamic (struct XDRInPacket *packet, void *buffer);
char *XDRInPacketGetString (struct XDRInPacket *packet); char *XDRInPacketGetString (struct XDRInPacket *packet);
void XDRInPacketSetTo (struct XDRInPacket *packet, uint8 *buffer, size_t offset); void XDRInPacketSetTo (struct XDRInPacket *packet, uint8 *buffer, size_t offset);
@@ -2,7 +2,12 @@
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
#include <ByteOrder.h> #include <ByteOrder.h>
#include <KernelExport.h>
#include <kernel.h>
extern const uint8 * extern const uint8 *
XDROutPacketBuffer(struct XDROutPacket *packet) XDROutPacketBuffer(struct XDROutPacket *packet)
@@ -49,29 +54,37 @@ XDROutPacketAddInt32(struct XDROutPacket *packet, int32 val)
packet->fLength+=4; packet->fLength+=4;
} }
extern void
status_t
XDROutPacketAddDynamic(struct XDROutPacket *packet, const void *data, size_t size) XDROutPacketAddDynamic(struct XDROutPacket *packet, const void *data, size_t size)
{ {
XDROutPacketAddInt32 (packet,size); XDROutPacketAddInt32(packet, size);
XDROutPacketAddFixed (packet,data,size); return XDROutPacketAddFixed(packet, data, size);
} }
extern void
status_t
XDROutPacketAddFixed(struct XDROutPacket *packet, const void *data, size_t size) XDROutPacketAddFixed(struct XDROutPacket *packet, const void *data, size_t size)
{ {
size_t roundedSize=(size+3)&~3; size_t roundedSize = (size + 3) & ~3;
XDROutPacketGrow (packet,roundedSize); XDROutPacketGrow(packet, roundedSize);
memcpy (&packet->fBuffer[packet->fLength],data,size); if (!IS_USER_ADDRESS(data))
memset (&packet->fBuffer[packet->fLength+size],0,roundedSize-size); memcpy(&packet->fBuffer[packet->fLength], data, size);
packet->fLength+=roundedSize; 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) XDROutPacketAddString(struct XDROutPacket *packet, const char *string)
{ {
XDROutPacketAddDynamic(packet,string,strlen(string)); return XDROutPacketAddDynamic(packet, string, strlen(string));
} }
extern void extern void
XDROutPacketAppend(struct XDROutPacket *me, const struct XDROutPacket *packet) XDROutPacketAppend(struct XDROutPacket *me, const struct XDROutPacket *packet)
{ {
@@ -18,9 +18,9 @@ void XDROutPacketDestroy (struct XDROutPacket *packet);
void XDROutPacketGrow (struct XDROutPacket *packet, size_t size); void XDROutPacketGrow (struct XDROutPacket *packet, size_t size);
void XDROutPacketAddInt32 (struct XDROutPacket *packet, int32 val); void XDROutPacketAddInt32 (struct XDROutPacket *packet, int32 val);
void XDROutPacketAddDynamic (struct XDROutPacket *packet, const void *data, size_t size); status_t XDROutPacketAddDynamic (struct XDROutPacket *packet, const void *data, size_t size);
void XDROutPacketAddFixed (struct XDROutPacket *packet, const void *data, size_t size); status_t XDROutPacketAddFixed (struct XDROutPacket *packet, const void *data, size_t size);
void XDROutPacketAddString (struct XDROutPacket *packet, const char *string); status_t XDROutPacketAddString (struct XDROutPacket *packet, const char *string);
void XDROutPacketAppend (struct XDROutPacket *me, const struct XDROutPacket *packet); void XDROutPacketAppend (struct XDROutPacket *me, const struct XDROutPacket *packet);
const uint8 *XDROutPacketBuffer (struct XDROutPacket *packet); const uint8 *XDROutPacketBuffer (struct XDROutPacket *packet);
@@ -389,7 +389,8 @@ is_successful_reply(struct XDRInPacket *reply)
} else { } else {
rpc_auth_flavor flavor = (rpc_auth_flavor)XDRInPacketGetInt32(reply); rpc_auth_flavor flavor = (rpc_auth_flavor)XDRInPacketGetInt32(reply);
char body[400]; 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); rpc_accept_stat acceptStat = (rpc_accept_stat)XDRInPacketGetInt32(reply);
(void)flavor; (void)flavor;
@@ -1554,7 +1555,9 @@ fs_read(fs_volume *_volume, fs_vnode *_node, void *_cookie, off_t pos,
get_nfs_attr(&reply, &st); get_nfs_attr(&reply, &st);
cookie->st = 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; buf = (char *)buf + readbytes;
(*len) += 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, 0);
XDROutPacketAddInt32(&call, pos + bytesWritten); XDROutPacketAddInt32(&call, pos + bytesWritten);
XDROutPacketAddInt32(&call, 0); 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, replyBuf = send_rpc_call(ns, &ns->nfsAddr, NFS_PROGRAM, NFS_VERSION,
NFSPROC_WRITE, &call); 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); return map_nfs_to_system_error(status);
} }
length = XDRInPacketGetDynamic(&reply, data); XDRInPacketGetDynamic(&reply, data, &length);
memcpy(buf, data, min_c(length, *bufsize)); memcpy(buf, data, min_c(length, *bufsize));
*bufsize = length; *bufsize = length;