[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] libdiskfs: fix reference counting of peropen objects
From: |
Justus Winter |
Subject: |
[PATCH] libdiskfs: fix reference counting of peropen objects |
Date: |
Fri, 29 Aug 2014 11:33:44 +0200 |
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.
---
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 +++---
6 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h
index e328527..e59ba99 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 45c4df5..a2e568b 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 69d78bc..649315f 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 011aa19..80c0b20 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 6d5ca01..788b9a7 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 22aaa2e..0b09299 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)
--
2.1.0
- [PATCH] libdiskfs: fix reference counting of peropen objects,
Justus Winter <=