deny setattr for size if not opened for write
proposes an alternate solution for attempts to set file size without an open sta teid. instead of acquiring one by sending OPEN, fail the request with ACCESS_DE NIED according the MS File System Algorithms documentation for setting FileAllocation Information and FileEndOfFileInformation [http://msdn.microsoft.com/en-us/librar y/ff469355%28v=PROT.10%29.aspx]: "If Open.GrantedAccess does not contain FILE_WRITE_DATA, the operation MUST be f ailed with STATUS_ACCESS_DENIED" -removes open_owner_id, access_mask, access_mode from setattr upcall arguments -moves map_access_2_allowdeny() back to open.c as a static function, since handl e_setattr() was its only other call site
This commit is contained in:
parent
9f2587c3b3
commit
2db91a3001
6 changed files with 53 additions and 104 deletions
|
|
@ -250,6 +250,40 @@ static int map_disposition_2_nfsopen(ULONG disposition, int in_status, bool_t pe
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void map_access_2_allowdeny(ULONG access_mask, ULONG access_mode,
|
||||||
|
uint32_t *allow, uint32_t *deny)
|
||||||
|
{
|
||||||
|
if ((access_mask & FILE_WRITE_DATA) &&
|
||||||
|
((access_mask & FILE_READ_DATA) ||
|
||||||
|
(access_mask & FILE_EXECUTE)))
|
||||||
|
*allow = OPEN4_SHARE_ACCESS_BOTH;
|
||||||
|
else if ((access_mask & FILE_READ_DATA) ||
|
||||||
|
(access_mask & FILE_EXECUTE))
|
||||||
|
*allow = OPEN4_SHARE_ACCESS_READ;
|
||||||
|
else if (access_mask & FILE_WRITE_DATA ||
|
||||||
|
(access_mask & FILE_APPEND_DATA) ||
|
||||||
|
(access_mask & FILE_WRITE_ATTRIBUTES))
|
||||||
|
*allow = OPEN4_SHARE_ACCESS_WRITE;
|
||||||
|
#define FIX_ALLOW_DENY_WIN2NFS_CONVERSION
|
||||||
|
#ifdef FIX_ALLOW_DENY_WIN2NFS_CONVERSION
|
||||||
|
if ((access_mode & FILE_SHARE_READ) &&
|
||||||
|
(access_mode & FILE_SHARE_WRITE))
|
||||||
|
*deny = OPEN4_SHARE_DENY_NONE;
|
||||||
|
else if (access_mode & FILE_SHARE_READ)
|
||||||
|
*deny = OPEN4_SHARE_DENY_WRITE;
|
||||||
|
else if (access_mode & FILE_SHARE_WRITE)
|
||||||
|
*deny = OPEN4_SHARE_DENY_READ;
|
||||||
|
else
|
||||||
|
*deny = OPEN4_SHARE_DENY_BOTH;
|
||||||
|
#else
|
||||||
|
// AGLO: 11/13/2009.
|
||||||
|
// readonly file that is being opened for reading with a
|
||||||
|
// share read mode given above logic translates into deny
|
||||||
|
// write and linux server does not allow it.
|
||||||
|
*deny = OPEN4_SHARE_DENY_NONE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static int check_execute_access(nfs41_open_state *state)
|
static int check_execute_access(nfs41_open_state *state)
|
||||||
{
|
{
|
||||||
uint32_t supported, access;
|
uint32_t supported, access;
|
||||||
|
|
|
||||||
|
|
@ -52,19 +52,11 @@ static int parse_setattr(unsigned char *buffer, uint32_t length, nfs41_upcall *u
|
||||||
}
|
}
|
||||||
status = safe_read(&buffer, &length, args->buf, args->buf_len);
|
status = safe_read(&buffer, &length, args->buf, args->buf_len);
|
||||||
if (status) goto out_free;
|
if (status) goto out_free;
|
||||||
status = safe_read(&buffer, &length, &args->open_owner_id, sizeof(ULONG));
|
|
||||||
if (status) goto out_free;
|
|
||||||
status = safe_read(&buffer, &length, &args->access_mask, sizeof(ULONG));
|
|
||||||
if (status) goto out_free;
|
|
||||||
status = safe_read(&buffer, &length, &args->access_mode, sizeof(ULONG));
|
|
||||||
if (status) goto out_free;
|
|
||||||
args->root = upcall->root_ref;
|
args->root = upcall->root_ref;
|
||||||
args->state = upcall->state_ref;
|
args->state = upcall->state_ref;
|
||||||
|
|
||||||
dprintf(1, "parsing NFS41_FILE_SET: filename='%s' info_class=%d "
|
dprintf(1, "parsing NFS41_FILE_SET: filename='%s' info_class=%d "
|
||||||
"buf_len=%d\nopen_owner_id=%d access_mask=%x access_mode=%x\n",
|
"buf_len=%d\n", args->path, args->set_class, args->buf_len);
|
||||||
args->path, args->set_class, args->buf_len, args->open_owner_id,
|
|
||||||
args->access_mask, args->access_mode);
|
|
||||||
out:
|
out:
|
||||||
return status;
|
return status;
|
||||||
out_free:
|
out_free:
|
||||||
|
|
@ -467,29 +459,6 @@ static int handle_setattr(nfs41_upcall *upcall)
|
||||||
nfs41_open_state *state = upcall->state_ref;
|
nfs41_open_state *state = upcall->state_ref;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
switch (args->set_class) {
|
|
||||||
case FileAllocationInformation:
|
|
||||||
case FileEndOfFileInformation:
|
|
||||||
if (!state->do_close) {
|
|
||||||
// get a stateid
|
|
||||||
StringCchPrintfA((LPSTR)state->owner.owner, NFS4_OPAQUE_LIMIT,
|
|
||||||
"%u", args->open_owner_id);
|
|
||||||
state->owner.owner_len = (uint32_t)strlen(
|
|
||||||
(const char*)state->owner.owner);
|
|
||||||
map_access_2_allowdeny(args->access_mask, args->access_mode,
|
|
||||||
&state->share_access, &state->share_deny);
|
|
||||||
status = nfs41_open(state->session, state->share_access,
|
|
||||||
state->share_deny, OPEN4_NOCREATE, 0, 0, TRUE, state, NULL);
|
|
||||||
if (status) {
|
|
||||||
dprintf(1, "nfs41_open() failed with %s\n", nfs_error_string(status));
|
|
||||||
status = nfs_to_windows_error(status, ERROR_FILE_NOT_FOUND);
|
|
||||||
goto out;
|
|
||||||
} else
|
|
||||||
client_state_add(state);
|
|
||||||
state->do_close = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (args->set_class) {
|
switch (args->set_class) {
|
||||||
case FileBasicInformation:
|
case FileBasicInformation:
|
||||||
status = handle_nfs41_setattr(args);
|
status = handle_nfs41_setattr(args);
|
||||||
|
|
@ -513,7 +482,7 @@ static int handle_setattr(nfs41_upcall *upcall)
|
||||||
status = ERROR_NOT_SUPPORTED;
|
status = ERROR_NOT_SUPPORTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
free(args->buf);
|
free(args->buf);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,9 +96,6 @@ typedef struct __setattr_upcall_args {
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
uint32_t buf_len;
|
uint32_t buf_len;
|
||||||
int set_class;
|
int set_class;
|
||||||
ULONG open_owner_id;
|
|
||||||
ULONG access_mask;
|
|
||||||
ULONG access_mode;
|
|
||||||
} setattr_upcall_args;
|
} setattr_upcall_args;
|
||||||
|
|
||||||
typedef struct __setexattr_upcall_args {
|
typedef struct __setexattr_upcall_args {
|
||||||
|
|
|
||||||
|
|
@ -222,41 +222,6 @@ void get_nfs_time(
|
||||||
file_time_to_nfs_time(&file_time, nfs_time);
|
file_time_to_nfs_time(&file_time, nfs_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void map_access_2_allowdeny(ULONG access_mask, ULONG access_mode,
|
|
||||||
uint32_t *allow, uint32_t *deny)
|
|
||||||
{
|
|
||||||
if ((access_mask & FILE_WRITE_DATA) &&
|
|
||||||
((access_mask & FILE_READ_DATA) ||
|
|
||||||
(access_mask & FILE_EXECUTE)))
|
|
||||||
*allow = OPEN4_SHARE_ACCESS_BOTH;
|
|
||||||
else if ((access_mask & FILE_READ_DATA) ||
|
|
||||||
(access_mask & FILE_EXECUTE))
|
|
||||||
*allow = OPEN4_SHARE_ACCESS_READ;
|
|
||||||
else if (access_mask & FILE_WRITE_DATA ||
|
|
||||||
(access_mask & FILE_APPEND_DATA) ||
|
|
||||||
(access_mask & FILE_WRITE_ATTRIBUTES))
|
|
||||||
*allow = OPEN4_SHARE_ACCESS_WRITE;
|
|
||||||
#define FIX_ALLOW_DENY_WIN2NFS_CONVERSION
|
|
||||||
#ifdef FIX_ALLOW_DENY_WIN2NFS_CONVERSION
|
|
||||||
if ((access_mode & FILE_SHARE_READ) &&
|
|
||||||
(access_mode & FILE_SHARE_WRITE))
|
|
||||||
*deny = OPEN4_SHARE_DENY_NONE;
|
|
||||||
else if (access_mode & FILE_SHARE_READ)
|
|
||||||
*deny = OPEN4_SHARE_DENY_WRITE;
|
|
||||||
else if (access_mode & FILE_SHARE_WRITE)
|
|
||||||
*deny = OPEN4_SHARE_DENY_READ;
|
|
||||||
else
|
|
||||||
*deny = OPEN4_SHARE_DENY_BOTH;
|
|
||||||
#else
|
|
||||||
// AGLO: 11/13/2009.
|
|
||||||
// readonly file that is being opened for reading with a
|
|
||||||
// share read mode given above logic translates into deny
|
|
||||||
// write and linux server does not allow it.
|
|
||||||
*deny = OPEN4_SHARE_DENY_NONE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool_t multi_addr_find(
|
bool_t multi_addr_find(
|
||||||
IN const multi_addr4 *addrs,
|
IN const multi_addr4 *addrs,
|
||||||
IN const netaddr4 *addr,
|
IN const netaddr4 *addr,
|
||||||
|
|
|
||||||
|
|
@ -139,12 +139,6 @@ int create_silly_rename(
|
||||||
IN const nfs41_fh *fh,
|
IN const nfs41_fh *fh,
|
||||||
OUT nfs41_component *silly);
|
OUT nfs41_component *silly);
|
||||||
|
|
||||||
void map_access_2_allowdeny(
|
|
||||||
IN ULONG access_mask,
|
|
||||||
IN ULONG access_mode,
|
|
||||||
OUT uint32_t *allow,
|
|
||||||
OUT uint32_t *deny);
|
|
||||||
|
|
||||||
bool_t multi_addr_find(
|
bool_t multi_addr_find(
|
||||||
IN const multi_addr4 *addrs,
|
IN const multi_addr4 *addrs,
|
||||||
IN const netaddr4 *addr,
|
IN const netaddr4 *addr,
|
||||||
|
|
|
||||||
|
|
@ -179,9 +179,6 @@ typedef struct _updowncall_entry {
|
||||||
PVOID buf;
|
PVOID buf;
|
||||||
ULONG buf_len;
|
ULONG buf_len;
|
||||||
FILE_INFORMATION_CLASS InfoClass;
|
FILE_INFORMATION_CLASS InfoClass;
|
||||||
ULONG open_owner_id;
|
|
||||||
ULONG access_mask;
|
|
||||||
ULONG access_mode;
|
|
||||||
} SetFile;
|
} SetFile;
|
||||||
struct {
|
struct {
|
||||||
DWORD mode;
|
DWORD mode;
|
||||||
|
|
@ -900,18 +897,11 @@ NTSTATUS marshal_nfs41_fileset(nfs41_updowncall_entry *entry,
|
||||||
tmp += sizeof(ULONG);
|
tmp += sizeof(ULONG);
|
||||||
RtlCopyMemory(tmp, entry->u.SetFile.buf, entry->u.SetFile.buf_len);
|
RtlCopyMemory(tmp, entry->u.SetFile.buf, entry->u.SetFile.buf_len);
|
||||||
tmp += entry->u.SetFile.buf_len;
|
tmp += entry->u.SetFile.buf_len;
|
||||||
RtlCopyMemory(tmp, &entry->u.SetFile.open_owner_id, sizeof(ULONG));
|
|
||||||
tmp += sizeof(ULONG);
|
|
||||||
RtlCopyMemory(tmp, &entry->u.SetFile.access_mask, sizeof(ULONG));
|
|
||||||
tmp += sizeof(ULONG);
|
|
||||||
RtlCopyMemory(tmp, &entry->u.SetFile.access_mode, sizeof(ULONG));
|
|
||||||
|
|
||||||
*len = header_len;
|
*len = header_len;
|
||||||
|
|
||||||
DbgP("marshal_nfs41_fileset: filename='%wZ' class=%d open_owner_id=0x%x "
|
DbgP("marshal_nfs41_fileset: filename='%wZ' class=%d\n",
|
||||||
"access_mask=0x%x access_mode=0x%x\n", entry->u.SetFile.filename,
|
entry->u.SetFile.filename, entry->u.SetFile.InfoClass);
|
||||||
entry->u.SetFile.InfoClass, entry->u.SetFile.open_owner_id,
|
|
||||||
entry->u.SetFile.access_mask, entry->u.SetFile.access_mode);
|
|
||||||
print_hexbuf(0, (unsigned char *)"setfile buffer", entry->u.SetFile.buf,
|
print_hexbuf(0, (unsigned char *)"setfile buffer", entry->u.SetFile.buf,
|
||||||
entry->u.SetFile.buf_len);
|
entry->u.SetFile.buf_len);
|
||||||
out:
|
out:
|
||||||
|
|
@ -4012,12 +4002,24 @@ NTSTATUS nfs41_SetFileInformation (
|
||||||
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
||||||
PNFS41_FCB nfs41_fcb = (PNFS41_FCB)(RxContext->pFcb)->Context;
|
PNFS41_FCB nfs41_fcb = (PNFS41_FCB)(RxContext->pFcb)->Context;
|
||||||
FILE_RENAME_INFORMATION rinfo;
|
FILE_RENAME_INFORMATION rinfo;
|
||||||
PFILE_OBJECT fo = RxContext->CurrentIrpSp->FileObject;
|
|
||||||
PNFS41_NETROOT_EXTENSION pNetRootContext =
|
PNFS41_NETROOT_EXTENSION pNetRootContext =
|
||||||
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
||||||
|
|
||||||
DbgEn();
|
DbgEn();
|
||||||
print_setfile_args(RxContext);
|
print_setfile_args(RxContext);
|
||||||
|
/* http://msdn.microsoft.com/en-us/library/ff469355(v=PROT.10).aspx
|
||||||
|
* http://msdn.microsoft.com/en-us/library/ff469424(v=PROT.10).aspx
|
||||||
|
* If Open.GrantedAccess does not contain FILE_WRITE_DATA, the operation
|
||||||
|
* MUST be failed with STATUS_ACCESS_DENIED.
|
||||||
|
*/
|
||||||
|
if (InfoClass == FileAllocationInformation ||
|
||||||
|
InfoClass == FileEndOfFileInformation) {
|
||||||
|
if (!(SrvOpen->DesiredAccess & FILE_WRITE_DATA)) {
|
||||||
|
status = STATUS_ACCESS_DENIED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (InfoClass) {
|
switch (InfoClass) {
|
||||||
case FileRenameInformation:
|
case FileRenameInformation:
|
||||||
{
|
{
|
||||||
|
|
@ -4096,19 +4098,7 @@ NTSTATUS nfs41_SetFileInformation (
|
||||||
goto out;
|
goto out;
|
||||||
entry->u.SetFile.filename = FileName;
|
entry->u.SetFile.filename = FileName;
|
||||||
entry->u.SetFile.InfoClass = InfoClass;
|
entry->u.SetFile.InfoClass = InfoClass;
|
||||||
switch(InfoClass) {
|
|
||||||
case FileAllocationInformation:
|
|
||||||
case FileEndOfFileInformation:
|
|
||||||
entry->u.SetFile.open_owner_id = get_next_open_owner();
|
|
||||||
if (fo->ReadAccess)
|
|
||||||
entry->u.SetFile.access_mask = FILE_READ_DATA;
|
|
||||||
if (fo->WriteAccess)
|
|
||||||
entry->u.SetFile.access_mask |= FILE_WRITE_DATA;
|
|
||||||
if (fo->SharedRead)
|
|
||||||
entry->u.SetFile.access_mode = FILE_SHARE_READ;
|
|
||||||
if (fo->SharedWrite)
|
|
||||||
entry->u.SetFile.access_mode |= FILE_SHARE_WRITE;
|
|
||||||
}
|
|
||||||
if (RxContext->Info.FileInformationClass == FileDispositionInformation &&
|
if (RxContext->Info.FileInformationClass == FileDispositionInformation &&
|
||||||
InfoClass == FileRenameInformation) {
|
InfoClass == FileRenameInformation) {
|
||||||
entry->u.SetFile.buf = &rinfo;
|
entry->u.SetFile.buf = &rinfo;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue