On Mon, Sep 11, 2006 at 03:59:45PM +, Paul Stoeber wrote:
Let's see if I can get this closer to right.
The patch is against and tested on -current.
Thank you, Pedro, for your help.
Paul,
Here's a slightly revised version of your patch. It would be nice to
have a couple of test reports on it (from people on misc@).
-p.
Index: sys/dev/vnd.c
===
RCS file: /cvs/src/sys/dev/vnd.c,v
retrieving revision 1.62
diff -u -p -r1.62 vnd.c
--- sys/dev/vnd.c 13 Aug 2006 17:55:07 - 1.62
+++ sys/dev/vnd.c 19 Sep 2006 15:40:17 -
@@ -142,6 +142,9 @@ struct vnd_softc {
#defineVNF_HAVELABEL 0x0400
#defineVNF_BUSY0x0800
#defineVNF_SIMPLE 0x1000
+#defineVNF_READONLY0x2000
+
+#defineVNDRW(v)((v)-sc_flags VNF_READONLY ? FREAD :
FREAD|FWRITE)
struct vnd_softc *vnd_softc;
int numvnd = 0;
@@ -234,6 +237,11 @@ vndopen(dev, flags, mode, p)
if ((error = vndlock(sc)) != 0)
return (error);
+ if ((flags FWRITE) (sc-sc_flags VNF_READONLY)) {
+ error = EROFS;
+ goto bad;
+ }
+
if ((sc-sc_flags VNF_INITED)
(sc-sc_flags VNF_HAVELABEL) == 0) {
sc-sc_flags |= VNF_HAVELABEL;
@@ -817,20 +825,26 @@ vndioctl(dev, cmd, addr, flag, p)
}
/*
-* Always open for read and write.
-* This is probably bogus, but it lets vn_open()
-* weed out directories, sockets, etc. so we don't
-* have to worry about them.
+* Open for read and write first. This lets vn_open() weed out
+* directories, sockets, etc. so we don't have to worry about
+* them.
*/
NDINIT(nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio-vnd_file, p);
- if ((error = vn_open(nd, FREAD|FWRITE, 0)) != 0) {
+ vnd-sc_flags = ~VNF_READONLY;
+ error = vn_open(nd, FREAD|FWRITE, 0);
+ if (error == EROFS) {
+ vnd-sc_flags |= VNF_READONLY;
+ error = vn_open(nd, FREAD, 0);
+ }
+ if (error) {
vndunlock(vnd);
return (error);
}
+
error = VOP_GETATTR(nd.ni_vp, vattr, p-p_ucred, p);
if (error) {
VOP_UNLOCK(nd.ni_vp, 0, p);
- (void) vn_close(nd.ni_vp, FREAD|FWRITE, p-p_ucred, p);
+ (void) vn_close(nd.ni_vp, VNDRW(vnd), p-p_ucred, p);
vndunlock(vnd);
return (error);
}
@@ -838,7 +852,7 @@ vndioctl(dev, cmd, addr, flag, p)
vnd-sc_vp = nd.ni_vp;
vnd-sc_size = btodb(vattr.va_size);/* note truncation */
if ((error = vndsetcred(vnd, p-p_ucred)) != 0) {
- (void) vn_close(nd.ni_vp, FREAD|FWRITE, p-p_ucred, p);
+ (void) vn_close(nd.ni_vp, VNDRW(vnd), p-p_ucred, p);
vndunlock(vnd);
return (error);
}
@@ -851,7 +865,7 @@ vndioctl(dev, cmd, addr, flag, p)
if ((error = copyin(vio-vnd_key, key,
vio-vnd_keylen)) != 0) {
- (void) vn_close(nd.ni_vp, FREAD|FWRITE,
+ (void) vn_close(nd.ni_vp, VNDRW(vnd),
p-p_ucred, p);
vndunlock(vnd);
return (error);
@@ -1087,7 +1101,7 @@ vndclear(vnd)
vnd-sc_flags = ~VNF_INITED;
if (vp == (struct vnode *)0)
panic(vndioctl: null vp);
- (void) vn_close(vp, FREAD|FWRITE, vnd-sc_cred, p);
+ (void) vn_close(vp, VNDRW(vnd), vnd-sc_cred, p);
crfree(vnd-sc_cred);
vnd-sc_vp = (struct vnode *)0;
vnd-sc_cred = (struct ucred *)0;
Index: usr.sbin/vnconfig/vnconfig.c
===
RCS file: /cvs/src/usr.sbin/vnconfig/vnconfig.c,v
retrieving revision 1.18
diff -u -p -r1.18 vnconfig.c
--- usr.sbin/vnconfig/vnconfig.c1 Jul 2006 07:36:27 - 1.18
+++ usr.sbin/vnconfig/vnconfig.c19 Sep 2006 15:40:17 -
@@ -226,9 +226,9 @@ config(char *dev, char *file, int action
char *rdev;
int rv;
- if (opendev(dev, O_RDWR, OPENDEV_PART, rdev) 0)
+ if (opendev(dev, O_RDONLY, OPENDEV_PART, rdev) 0)
err(4, %s, rdev);
- f = fopen(rdev, rw);
+ f = fopen(rdev, r);
if (f == NULL) {
warn(%s, rdev);
rv = -1;