From 520ef2ed66d47bb81a55829a88dda81f62dc95e5 Mon Sep 17 00:00:00 2001 From: Justus Winter <4winter@informatik.uni-hamburg.de> Date: Fri, 20 Jun 2014 13:54:28 +0200 Subject: libdiskfs: fix reference counting of peropen objects Previously, peropen objects were created with a reference count of zero. Therefore, if diskfs_create_protid fails, passing such an object to diskfs_release_peropen would lead to a reference count underflow. * libdiskfs/peropen-make.c (diskfs_peropen_make): Initialize reference count to one. * libdiskfs/protid-make.c (diskfs_start_protid): And consume this reference on success. Update comment. (diskfs_create_protid): Update comment. * libdiskfs/diskfs.h: Update comments. * libdiskfs/io-duplicate.c (diskfs_S_io_duplicate): Adjust reference counting accordingly. * libdiskfs/io-reauthenticate.c (diskfs_S_io_reauthenticate): Likewise. * libdiskfs/io-restrict-auth.c (diskfs_S_io_restrict_auth): Likewise. * doc/hurd.texi (Diskfs Internals): Update accordingly. --- doc/hurd.texi | 4 ++-- libdiskfs/diskfs.h | 4 ++-- libdiskfs/io-duplicate.c | 3 +++ libdiskfs/io-reauthenticate.c | 2 ++ libdiskfs/io-restrict-auth.c | 3 +++ libdiskfs/peropen-make.c | 2 +- libdiskfs/protid-make.c | 6 +++--- 7 files changed, 16 insertions(+), 8 deletions(-) diff --git a/doc/hurd.texi b/doc/hurd.texi index 07ddfb46..8fa6da72 100644 --- a/doc/hurd.texi +++ b/doc/hurd.texi @@ -4431,13 +4431,13 @@ provides. @deftypefun error_t diskfs_create_protid (@w{struct peropen *@var{po}}, @w{struct iouser *@var{user}}, @w{struct protid **@var{cred}}) Create and return a protid for an existing peropen @var{po} in @var{cred}, referring to user @var{user}. The node @code{@var{po}->np} -must be locked. +must be locked. On success, a reference to @var{po} is consumed. @end deftypefun @deftypefun error_t diskfs_start_protid (@w{struct peropen *@var{po}}, @w{struct protid **@var{cred}}) Build and return in @var{cred} a protid which has no user identification, for peropen @var{po}. The node @code{@var{po}->np} must -be locked. +be locked. On success, a reference to @var{po} is consumed. @end deftypefun @deftypefun void diskfs_finish_protid (@w{struct protid *@var{cred}}, @w{struct iouser *@var{user}}) diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h index e3285271..e59ba996 100644 --- a/libdiskfs/diskfs.h +++ b/libdiskfs/diskfs.h @@ -820,12 +820,12 @@ diskfs_create_node (struct node *dir, const char *name, mode_t mode, struct dirstat *ds); /* Create and return a protid for an existing peropen PO in CRED, - referring to user USER. */ + referring to user USER. On success, consume a reference to PO. */ error_t diskfs_create_protid (struct peropen *po, struct iouser *user, struct protid **cred); /* Build and return in CRED a protid which has no user identification, for - peropen PO. */ + peropen PO. On success, consume a reference to PO. */ error_t diskfs_start_protid (struct peropen *po, struct protid **cred); /* Finish building protid CRED started with diskfs_start_protid; diff --git a/libdiskfs/io-duplicate.c b/libdiskfs/io-duplicate.c index 45c4df5d..a2e568b7 100644 --- a/libdiskfs/io-duplicate.c +++ b/libdiskfs/io-duplicate.c @@ -32,6 +32,7 @@ diskfs_S_io_duplicate (struct protid *cred, pthread_mutex_lock (&cred->po->np->lock); + refcount_ref (&cred->po->refcnt); err = diskfs_create_protid (cred->po, cred->user, &newpi); if (! err) { @@ -39,6 +40,8 @@ diskfs_S_io_duplicate (struct protid *cred, *portpoly = MACH_MSG_TYPE_MAKE_SEND; ports_port_deref (newpi); } + else + refcount_deref (&cred->po->refcnt); pthread_mutex_unlock (&cred->po->np->lock); diff --git a/libdiskfs/io-reauthenticate.c b/libdiskfs/io-reauthenticate.c index 69d78bc5..649315f7 100644 --- a/libdiskfs/io-reauthenticate.c +++ b/libdiskfs/io-reauthenticate.c @@ -35,11 +35,13 @@ diskfs_S_io_reauthenticate (struct protid *cred, are a simpleroutine, so callers won't know to restart. */ pthread_mutex_lock (&cred->po->np->lock); + refcount_ref (&cred->po->refcnt); do err = diskfs_start_protid (cred->po, &newcred); while (err == EINTR); if (err) { + refcount_deref (&cred->po->refcnt); pthread_mutex_unlock (&cred->po->np->lock); return err; } diff --git a/libdiskfs/io-restrict-auth.c b/libdiskfs/io-restrict-auth.c index 011aa19e..80c0b208 100644 --- a/libdiskfs/io-restrict-auth.c +++ b/libdiskfs/io-restrict-auth.c @@ -41,6 +41,7 @@ diskfs_S_io_restrict_auth (struct protid *cred, return err; pthread_mutex_lock (&cred->po->np->lock); + refcount_ref (&cred->po->refcnt); err = diskfs_create_protid (cred->po, user, &newpi); if (! err) { @@ -48,6 +49,8 @@ diskfs_S_io_restrict_auth (struct protid *cred, *newportpoly = MACH_MSG_TYPE_MAKE_SEND; ports_port_deref (newpi); } + else + refcount_deref (&cred->po->refcnt); pthread_mutex_unlock (&cred->po->np->lock); iohelp_free_iouser (user); diff --git a/libdiskfs/peropen-make.c b/libdiskfs/peropen-make.c index 6d5ca014..788b9a7a 100644 --- a/libdiskfs/peropen-make.c +++ b/libdiskfs/peropen-make.c @@ -31,7 +31,7 @@ diskfs_make_peropen (struct node *np, int flags, struct peropen *context, po->filepointer = 0; po->lock_status = LOCK_UN; - refcount_init (&po->refcnt, 0); + refcount_init (&po->refcnt, 1); po->openstat = flags; po->np = np; po->path = NULL; diff --git a/libdiskfs/protid-make.c b/libdiskfs/protid-make.c index 22aaa2e1..0b092994 100644 --- a/libdiskfs/protid-make.c +++ b/libdiskfs/protid-make.c @@ -20,7 +20,7 @@ #include /* Build and return in CRED a protid which has no user identification, for - peropen PO. */ + peropen PO. On success, consume a reference to PO. */ error_t diskfs_start_protid (struct peropen *po, struct protid **cred) { @@ -29,7 +29,7 @@ diskfs_start_protid (struct peropen *po, struct protid **cred) sizeof (struct protid), cred); if (! err) { - refcount_ref (&po->refcnt); + /* Consume a reference to po. */ (*cred)->po = po; (*cred)->shared_object = MACH_PORT_NULL; (*cred)->mapped = 0; @@ -56,7 +56,7 @@ diskfs_finish_protid (struct protid *cred, struct iouser *user) } /* Create and return a protid for an existing peropen PO in CRED for - USER. */ + USER. On success, consume a reference to PO. */ error_t diskfs_create_protid (struct peropen *po, struct iouser *user, struct protid **cred) -- cgit v1.2.3