vfs: fix null deref, pfs: add fchmod()
. vfs read_only() assumes vnode->v_vmnt is non-NULL, but it can be NULL sometimes . e.g. fchmod() on UDS triggered NULL deref; add a check and add REQ_CHMOD to pfs so unix domain sockets can be fchmod()ded . add to test56 Change-Id: I83c840f101b647516897cc99fcf472116d762012
This commit is contained in:
parent
04ad4fa1a2
commit
072d916c1c
5 changed files with 58 additions and 2 deletions
|
@ -1,4 +1,5 @@
|
|||
#include "fs.h"
|
||||
#include "inode.h"
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
|
@ -10,3 +11,18 @@ int fs_sync(message *fs_m_in, message *fs_m_out)
|
|||
|
||||
return(OK); /* sync() can't fail */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* fs_chmod *
|
||||
*===========================================================================*/
|
||||
int fs_chmod(message *fs_m_in, message *fs_m_out)
|
||||
{
|
||||
struct inode *rip; /* target inode */
|
||||
mode_t mode = (mode_t) fs_m_in->REQ_MODE;
|
||||
|
||||
if( (rip = find_inode(fs_m_in->REQ_INODE_NR)) == NULL) return(EINVAL);
|
||||
get_inode(rip->i_dev, rip->i_num); /* mark inode in use */
|
||||
rip->i_mode = (rip->i_mode & ~ALL_MODES) | (mode & ALL_MODES);
|
||||
put_inode(rip); /* release the inode */
|
||||
return OK;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ void reply(endpoint_t who, message *m_out);
|
|||
|
||||
/* misc.c */
|
||||
int fs_sync(message *fs_m_in, message *fs_m_out);
|
||||
int fs_chmod(message *fs_m_in, message *fs_m_out);
|
||||
|
||||
/* mount.c */
|
||||
int fs_unmount(message *fs_m_in, message *fs_m_out);
|
||||
|
|
|
@ -19,7 +19,7 @@ int (*fs_call_vec[])(message *fs_m_in, message *fs_m_out) = {
|
|||
no_sys, /* 3 */
|
||||
fs_ftrunc, /* 4 */
|
||||
no_sys, /* 5 */
|
||||
no_sys, /* 6 */
|
||||
fs_chmod, /* 6 */
|
||||
no_sys, /* 7 */
|
||||
fs_stat, /* 8 */
|
||||
no_sys, /* 9 */
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "fs.h"
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <minix/callnr.h>
|
||||
#include "file.h"
|
||||
#include "fproc.h"
|
||||
|
@ -62,9 +63,12 @@ int do_chmod(message *UNUSED(m_out))
|
|||
/* File is already opened; get a pointer to vnode from filp. */
|
||||
if ((flp = get_filp(rfd, VNODE_WRITE)) == NULL) return(err_code);
|
||||
vp = flp->filp_vno;
|
||||
assert(vp);
|
||||
dup_vnode(vp);
|
||||
}
|
||||
|
||||
assert(vp);
|
||||
|
||||
/* Only the owner or the super_user may change the mode of a file.
|
||||
* No one may change the mode of a file on a read-only file system.
|
||||
*/
|
||||
|
@ -304,5 +308,6 @@ struct vnode *vp; /* ptr to inode whose file sys is to be cked */
|
|||
/* Check to see if the file system on which the inode 'ip' resides is mounted
|
||||
* read only. If so, return EROFS, else return OK.
|
||||
*/
|
||||
return((vp->v_vmnt->m_flags & VMNT_READONLY) ? EROFS : OK);
|
||||
assert(vp);
|
||||
return(vp->v_vmnt && (vp->v_vmnt->m_flags & VMNT_READONLY) ? EROFS : OK);
|
||||
}
|
||||
|
|
|
@ -2852,6 +2852,39 @@ void test_select()
|
|||
|
||||
}
|
||||
|
||||
void test_fchmod()
|
||||
{
|
||||
int socks[2];
|
||||
struct stat st1, st2;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) < 0) {
|
||||
test_fail("Can't open socket pair.");
|
||||
}
|
||||
|
||||
if (fstat(socks[0], &st1) < 0 || fstat(socks[1], &st2) < 0) {
|
||||
test_fail("fstat failed.");
|
||||
}
|
||||
|
||||
if ((st1.st_mode & (S_IRUSR|S_IWUSR)) == S_IRUSR &&
|
||||
(st2.st_mode & (S_IRUSR|S_IWUSR)) == S_IWUSR) {
|
||||
test_fail("fstat failed.");
|
||||
}
|
||||
|
||||
if (fchmod(socks[0], S_IRUSR) < 0 ||
|
||||
fstat(socks[0], &st1) < 0 ||
|
||||
(st1.st_mode & (S_IRUSR|S_IWUSR)) != S_IRUSR) {
|
||||
test_fail("fchmod/fstat mode set/check failed (1).");
|
||||
}
|
||||
|
||||
if (fchmod(socks[1], S_IWUSR) < 0 || fstat(socks[1], &st2) < 0 ||
|
||||
(st2.st_mode & (S_IRUSR|S_IWUSR)) != S_IWUSR) {
|
||||
test_fail("fchmod/fstat mode set/check failed (2).");
|
||||
}
|
||||
|
||||
close(socks[0]);
|
||||
close(socks[1]);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
@ -2892,6 +2925,7 @@ int main(int argc, char *argv[])
|
|||
test_scm_credentials();
|
||||
test_fd_passing();
|
||||
test_select();
|
||||
test_fchmod();
|
||||
quit();
|
||||
|
||||
return -1; /* we should never get here */
|
||||
|
|
Loading…
Reference in a new issue