NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
bin/54829: rename operation crashes mount_9p if target file already exists
>Number: 54829
>Category: bin
>Synopsis: rename operation crashes mount_9p if target file already exists
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Jan 04 11:15:00 +0000 2020
>Originator: Nicola Girardi
>Release: 8.1
>Organization:
>Environment:
NetBSD hope 8.1 NetBSD 8.1 (GENERIC) #0: Fri May 31 08:43:59 UTC 2019 mkrepro%mkrepro.NetBSD.org@localhost:/usr/src/sys/arch/amd64/compile/GENERIC amd64
>Description:
I was trying to use a 9P fs in NetBSD and found mount_9p
crashes when on the rename op when the target file already exists.
AFAICS the first problem is passing pn_targ->pn_data instead of pn_targ to noderemove(), causing invalid memory access in noderemove().
The second problem seems to be the call to puffs_setback() from the rename handler, which fails an assertion and aborts the file server. Since mount_psshfs does not call puffs_setback() in the analogous situation (it also has to remove before rename if the target already exists), I've removed the call here as well, in my proposed fix below. I haven't studied the internals enough to be confident about the patch and can only say that it works for me.
>How-To-Repeat:
While I found the problem by cloning a git repository on a mounted 9P fs, this would be the minimal reproducer:
mount_9p yourhost /yourmnt
cd /yourmnt
touch a
touch b
mv a b
>Fix:
Proposed fix but needs more scrutiny.
; cvs diff -u
cvs diff: Diffing .
Index: node.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/puffs/mount_9p/node.c,v
retrieving revision 1.21
diff -u -r1.21 node.c
--- node.c 18 Jan 2009 10:10:47 -0000 1.21
+++ node.c 4 Jan 2020 10:05:31 -0000
@@ -516,11 +516,7 @@
p9n->fid_base = P9P_INVALFID;
puffs_pn_remove(pn);
}
-
- out:
- if (rv == 0)
- puffs_setback(pcc, PUFFS_SETBACK_NOREF_N2);
-
+out:
RETURN(rv);
}
@@ -528,24 +524,34 @@
puffs9p_node_remove(struct puffs_usermount *pu, void *opc, void *targ,
const struct puffs_cn *pcn)
{
+ struct puffs_cc *pcc = puffs_cc_getcc(pu);
+ int rv = 0;
struct puffs_node *pn = targ;
if (pn->pn_va.va_type == VDIR)
return EISDIR;
- return noderemove(pu, pn);
+ rv = noderemove(pu, pn);
+ if (rv == 0)
+ puffs_setback(pcc, PUFFS_SETBACK_NOREF_N2);
+ return rv;
}
int
puffs9p_node_rmdir(struct puffs_usermount *pu, void *opc, void *targ,
const struct puffs_cn *pcn)
{
+ struct puffs_cc *pcc = puffs_cc_getcc(pu);
+ int rv = 0;
struct puffs_node *pn = targ;
if (pn->pn_va.va_type != VDIR)
return ENOTDIR;
- return noderemove(pu, pn);
+ rv = noderemove(pu, pn);
+ if (rv == 0)
+ puffs_setback(pcc, PUFFS_SETBACK_NOREF_N2);
+ return rv;
}
/*
@@ -571,7 +577,7 @@
if (targ) {
struct puffs_node *pn_targ = targ;
- rv = noderemove(pu, pn_targ->pn_data);
+ rv = noderemove(pu, pn_targ);
if (rv)
goto out;
}
Home |
Main Index |
Thread Index |
Old Index