summaryrefslogtreecommitdiff
path: root/libdiskfs
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2014-06-20 13:54:28 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2014-08-31 12:35:10 +0200
commit520ef2ed66d47bb81a55829a88dda81f62dc95e5 (patch)
tree8f1f6722409557f40bd3eef097e28923b12d214a /libdiskfs
parentc19a90851170077b99e694262d002a6e22145b49 (diff)
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.
Diffstat (limited to 'libdiskfs')
-rw-r--r--libdiskfs/diskfs.h4
-rw-r--r--libdiskfs/io-duplicate.c3
-rw-r--r--libdiskfs/io-reauthenticate.c2
-rw-r--r--libdiskfs/io-restrict-auth.c3
-rw-r--r--libdiskfs/peropen-make.c2
-rw-r--r--libdiskfs/protid-make.c6
6 files changed, 14 insertions, 6 deletions
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 <assert.h>
/* 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)