windows-insert-locking-without-afsid-20060422

This patch disables the lookup of the user's AFSID and instead solves
the problem by tracking which cm_user_t created the file.  If the user
is unable to obtain a write lock and is the creator, then we check for
the Insert bit.  Otherwise, we deny access.
This commit is contained in:
Jeffrey Altman 2006-04-22 20:44:28 +00:00
parent d463c0f7c6
commit 237ab6e5ba
12 changed files with 122 additions and 91 deletions

View File

@ -32,8 +32,8 @@
* can't be locked. Thus, this must always be called in a while loop to stabilize
* things, since we can always lose the race condition getting to the parent vnode.
*/
int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *up, long rights,
long *outRightsp)
int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *up, afs_uint32 rights,
afs_uint32 *outRightsp)
{
cm_scache_t *aclScp;
long code;

View File

@ -13,7 +13,7 @@
#include "cm_user.h"
extern int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *up,
long rights, long *outRights);
afs_uint32 rights, afs_uint32 *outRights);
extern long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *up,
struct cm_req *reqp);

View File

@ -68,7 +68,7 @@ static void CleanupACLEnt(cm_aclent_t * aclp)
* Get an acl cache entry for a particular user and file, or return that it doesn't exist.
* Called with the scp locked.
*/
long cm_FindACLCache(cm_scache_t *scp, cm_user_t *userp, long *rightsp)
long cm_FindACLCache(cm_scache_t *scp, cm_user_t *userp, afs_uint32 *rightsp)
{
cm_aclent_t *aclp;
long retval = -1;
@ -147,7 +147,7 @@ static cm_aclent_t *GetFreeACLEnt(cm_scache_t * scp)
*
* The scp must be locked when this function is called.
*/
long cm_AddACLCache(cm_scache_t *scp, cm_user_t *userp, long rights)
long cm_AddACLCache(cm_scache_t *scp, cm_user_t *userp, afs_uint32 rights)
{
register struct cm_aclent *aclp;

View File

@ -25,7 +25,7 @@ typedef struct cm_aclent {
struct cm_aclent *nextp; /* next guy same vnode */
struct cm_scache *backp; /* back ptr to vnode */
struct cm_user *userp; /* user whose access is cached */
long randomAccess; /* watch for more rights in acl.h */
afs_uint32 randomAccess; /* watch for more rights in acl.h */
unsigned long tgtLifetime; /* time this expires */
} cm_aclent_t;
@ -33,11 +33,11 @@ extern osi_rwlock_t cm_aclLock;
extern long cm_InitACLCache(int newFile, long size);
extern long cm_FindACLCache(struct cm_scache *scp, struct cm_user *userp, long *rightsp);
extern long cm_FindACLCache(struct cm_scache *scp, struct cm_user *userp, afs_uint32 *rightsp);
static cm_aclent_t *GetFreeACLEnt(cm_scache_t * scp);
extern long cm_AddACLCache(struct cm_scache *scp, struct cm_user *userp, long rights);
extern long cm_AddACLCache(struct cm_scache *scp, struct cm_user *userp, afs_uint32 rights);
extern void cm_FreeAllACLEnts(struct cm_scache *scp);

View File

@ -1896,6 +1896,7 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
return code;
}
#ifdef QUERY_AFSID
long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
{
afs_int32 code;
@ -1970,7 +1971,7 @@ long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
return 0;
}
#endif /* QUERY_AFSID */
long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
{
@ -2088,11 +2089,14 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
ucellp->kvno = ct.AuthHandle;
ucellp->expirationTime = ct.EndTimestamp;
ucellp->gen++;
#ifdef QUERY_AFSID
ucellp->uid = ANONYMOUSID;
#endif
if (uname) {
StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
#ifdef QUERY_AFSID
cm_UsernameToId(uname, ucellp, &ucellp->uid);
#endif
}
ucellp->flags |= CM_UCELLFLAG_RXKAD;
lock_ReleaseMutex(&userp->mx);

View File

@ -668,12 +668,12 @@ cm_scache_t * cm_FindSCacheParent(cm_scache_t * scp)
* CM_SCACHESYNC_STOREDATA_EXCL and CM_SCACHEFLAG_DATASTORING.
*/
long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *up, cm_req_t *reqp,
long rights, long flags)
afs_uint32 rights, afs_uint32 flags)
{
osi_queueData_t *qdp;
long code;
cm_buf_t *tbufp;
long outRights;
afs_uint32 outRights;
int bufLocked;
/* lookup this first */
@ -874,7 +874,8 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *up, cm_req_t *reqp,
return CM_ERROR_READONLY;
if (cm_HaveAccessRights(scp, up, rights, &outRights)) {
if (~outRights & rights) return CM_ERROR_NOACCESS;
if (~outRights & rights)
return CM_ERROR_NOACCESS;
}
else {
/* we don't know the required access rights */
@ -990,7 +991,7 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *up, cm_req_t *reqp,
/* for those syncops that setup for RPCs.
* Called with scache locked.
*/
void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, long flags)
void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, afs_uint32 flags)
{
osi_queueData_t *qdp;
cm_buf_t *tbufp;
@ -1074,7 +1075,7 @@ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, long flags)
* started before that, can cause old info to be merged from the first call.
*/
void cm_MergeStatus(cm_scache_t *scp, AFSFetchStatus *statusp, AFSVolSync *volp,
cm_user_t *userp, int flags)
cm_user_t *userp, afs_uint32 flags)
{
// yj: i want to create some fake status for the /afs directory and the
// entries under that directory

View File

@ -23,14 +23,6 @@ typedef struct cm_fid {
unsigned long unique;
} cm_fid_t;
#if 0
typedef struct cm_accessCache {
osi_queue_t q; /* queue header */
struct cm_user *userp; /* user having access rights */
unsigned long rights; /* rights */
} cm_accessCache_t;
#endif
/* Key used for byte range locking. Each unique key identifies a
unique client per cm_scache_t for the purpose of locking. */
typedef afs_uint64 cm_key_t;
@ -130,6 +122,7 @@ typedef struct cm_scache {
afs_uint32 dataVersion; /* data version */
afs_uint32 owner; /* file owner */
afs_uint32 group; /* file owning group */
cm_user_t *creator; /* user, if new file */
/* pseudo file status */
osi_hyper_t serverLength; /* length known to server */
@ -317,12 +310,12 @@ extern cm_scache_t *cm_GetNewSCache(void);
extern int cm_FidCmp(cm_fid_t *, cm_fid_t *);
extern long cm_SyncOp(cm_scache_t *, struct cm_buf *, struct cm_user *,
struct cm_req *, long, long);
struct cm_req *, afs_uint32, afs_uint32);
extern void cm_SyncOpDone(cm_scache_t *, struct cm_buf *, long);
extern void cm_SyncOpDone(cm_scache_t *, struct cm_buf *, afs_uint32);
extern void cm_MergeStatus(cm_scache_t *, struct AFSFetchStatus *, struct AFSVolSync *,
struct cm_user *, int flags);
struct cm_user *, afs_uint32 flags);
extern void cm_AFSFidFromFid(struct AFSFid *, cm_fid_t *);

View File

@ -32,7 +32,9 @@ typedef struct cm_ucell {
int iterator; /* for use as ListTokens cookie */
long flags; /* flags */
char userName[MAXKTCNAMELEN]; /* user name */
#ifdef QUERY_AFSID
afs_uint32 uid; /* User's AFS ID in this cell */
#endif
} cm_ucell_t;
#define CM_UCELLFLAG_HASTIX 1 /* has Kerberos tickets */

View File

@ -2270,6 +2270,7 @@ long cm_Create(cm_scache_t *dscp, char *namep, long flags, cm_attr_t *attrp,
code = cm_GetSCache(&newFid, &scp, userp, reqp);
if (code == 0) {
lock_ObtainMutex(&scp->mx);
scp->creator = userp; /* remember who created it */
if (!cm_HaveCallback(scp)) {
cm_MergeStatus(scp, &newFileStatus, &volSync,
userp, 0);
@ -3434,7 +3435,8 @@ long cm_LockCheckPerms(cm_scache_t * scp,
CM_SCACHESYNC_NEEDCALLBACK);
if (code == CM_ERROR_NOACCESS &&
lock_type == LockWrite) {
lock_type == LockWrite &&
scp->creator == userp) {
/* check for PRSFS_INSERT. */
cm_ucell_t * ucp;
@ -3442,25 +3444,8 @@ long cm_LockCheckPerms(cm_scache_t * scp,
CM_SCACHESYNC_GETSTATUS |
CM_SCACHESYNC_NEEDCALLBACK);
if (code) {
if (code == CM_ERROR_NOACCESS)
osi_Log0(afsd_logp, "cm_LockCheckPerms user has no INSERT bits for scp");
goto return_code;
}
code = CM_ERROR_NOACCESS;
lock_ObtainMutex(&userp->mx);
for (ucp = userp->cellInfop; ucp; ucp = ucp->nextp) {
if (scp->fid.cell == ucp->cellp->cellID) {
if (scp->owner == ucp->uid)
code = 0;
break;
}
}
lock_ReleaseMutex(&userp->mx);
osi_Log0(afsd_logp, "cm_LockCheckPerms user is creator but has no INSERT bits for scp");
}
return_code:

View File

@ -5817,6 +5817,16 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
fidp->flags &= ~SMB_FID_DELONCLOSE;
}
/* if this was a newly created file, then clear the creator
* in the stat cache entry. */
if (fidp->flags & SMB_FID_CREATED) {
lock_ObtainMutex(&fidp->scp->mx);
if (fidp->scp->creator == userp)
fidp->scp->creator = NULL;
lock_ReleaseMutex(&fidp->scp->mx);
fidp->flags &= ~SMB_FID_CREATED;
}
if (fidp->flags & SMB_FID_NTOPEN) {
fidp->NTopen_dscp = NULL;
fidp->NTopen_pathp = NULL;
@ -6846,6 +6856,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
afs_uint32 dosTime;
char *tidPathp;
cm_req_t req;
int created = 0; /* the file was new */
cm_InitReq(&req);
@ -6945,11 +6956,13 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
if (code == 0) {
created = 1;
if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_FILE_NAME,
dscp, lastNamep, NULL, TRUE);
if (!excl && code == CM_ERROR_EXISTS) {
} else if (!excl && code == CM_ERROR_EXISTS) {
/* not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
@ -6994,6 +7007,10 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
/* always create it open for read/write */
fidp->flags |= (SMB_FID_OPENREAD | SMB_FID_OPENWRITE);
/* remember that the file was newly created */
if (created)
fidp->flags |= SMB_FID_CREATED;
/* save a pointer to the vnode */
fidp->scp = scp;
/* and the user */

View File

@ -358,7 +358,7 @@ typedef struct smb_fid {
#define SMB_FID_OPENREAD 1 /* open for reading */
#define SMB_FID_OPENWRITE 2 /* open for writing */
#define SMB_FID_UNUSED 4 /* free for use */
#define SMB_FID_CREATED 4 /* a new file */
#define SMB_FID_IOCTL 8 /* a file descriptor for the
* magic ioctl file */
#define SMB_FID_OPENDELETE 0x10 /* open for deletion (NT) */

View File

@ -2062,6 +2062,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
long returnEALength;
char *tidPathp;
cm_req_t req;
int created = 0;
cm_InitReq(&req);
@ -2280,11 +2281,13 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
smb_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
if (code == 0) {
created = 1;
if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_FILE_NAME,
dscp, lastNamep, NULL, TRUE);
if (!excl && code == CM_ERROR_EXISTS) {
} else if (!excl && code == CM_ERROR_EXISTS) {
/* not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
@ -2359,6 +2362,11 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
fidp->flags |= SMB_FID_OPENREAD;
if (openMode == 1 || openMode == 2)
fidp->flags |= SMB_FID_OPENWRITE;
/* remember that the file was newly created */
if (created)
fidp->flags |= SMB_FID_CREATED;
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
@ -4515,6 +4523,7 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
int parmSlot; /* which parm we're dealing with */
char *tidPathp;
cm_req_t req;
int created = 0;
cm_InitReq(&req);
@ -4697,11 +4706,13 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
if (code == 0) {
created = 1;
if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_FILE_NAME,
dscp, lastNamep, NULL, TRUE);
if (!excl && code == CM_ERROR_EXISTS) {
} else if (!excl && code == CM_ERROR_EXISTS) {
/* not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
@ -4757,6 +4768,10 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
if (openMode == 1 || openMode == 2)
fidp->flags |= SMB_FID_OPENWRITE;
/* remember if the file was newly created */
if (created)
fidp->flags |= SMB_FID_CREATED;
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
@ -5366,6 +5381,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
char *tidPathp;
BOOL foundscp;
cm_req_t req;
int created = 0;
cm_InitReq(&req);
@ -5798,11 +5814,13 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, &req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
if (code == 0) {
created = 1;
if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_FILE_NAME,
dscp, lastNamep, NULL, TRUE);
if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
} else if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
/* Not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
@ -6027,6 +6045,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
fidp->flags = fidflags;
/* remember if the file was newly created */
if (created)
fidp->flags |= SMB_FID_CREATED;
/* save parent dir and pathname for delete or change notification */
if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) {
fidp->flags |= SMB_FID_NTOPEN;
@ -6133,6 +6155,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
ULONG *lparmp;
char *outData;
cm_req_t req;
int created = 0;
cm_InitReq(&req);
@ -6466,11 +6489,13 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
setAttr.clientModTime = time(NULL);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
if (code == 0) {
created = 1;
if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_FILE_NAME,
dscp, lastNamep, NULL, TRUE);
if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
} else if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
/* Not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
@ -6627,6 +6652,10 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
fidp->flags = fidflags;
/* remember if the file was newly created */
if (created)
fidp->flags |= SMB_FID_CREATED;
/* save parent dir and pathname for deletion or change notification */
if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) {
fidp->flags |= SMB_FID_NTOPEN;