Currently, applications that wish to access security descriptors have to explicitly open the volume's security descriptor index ("$Secure") using ntfs_open_secure(). Applications are also responsible for closing the index when done with it. However, the cleanup function for doing, ntfs_close_secure(), cannot be called easily by all applications because it requires a SECURITY_CONTEXT argument, not simply the ntfs_volume. Some applications therefore have to close the inode and index contexts manually in order to clean up properly.
This proposal updates libntfs-3g to open $Secure unconditonally as part of ntfs_mount(), so that applications do not have to worry about it. ntfs_close_secure() is updated to take in a ntfs_volume for internal use, and ntfs_destroy_security_context() is now the function to call to free memory associated with a SECURITY_CONTEXT rather than a ntfs_volume. Some memory leaks in error paths of ntfs_open_secure() are also fixed. Signed-off-by: Eric Biggers <ebigge...@gmail.com> --- include/ntfs-3g/security.h | 4 ++- libntfs-3g/security.c | 87 ++++++++++++++++++++++++++++------------------ libntfs-3g/volume.c | 7 ++++ src/lowntfs-3g.c | 6 +--- src/ntfs-3g.c | 6 +--- 5 files changed, 65 insertions(+), 45 deletions(-) diff --git a/include/ntfs-3g/security.h b/include/ntfs-3g/security.h index b5c6375..d27599e 100644 --- a/include/ntfs-3g/security.h +++ b/include/ntfs-3g/security.h @@ -256,7 +256,9 @@ int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx, le32 ntfs_inherited_id(struct SECURITY_CONTEXT *scx, ntfs_inode *dir_ni, BOOL fordir); int ntfs_open_secure(ntfs_volume *vol); -void ntfs_close_secure(struct SECURITY_CONTEXT *scx); +void ntfs_close_secure(ntfs_volume *vol); + +void ntfs_destroy_security_context(struct SECURITY_CONTEXT *scx); #if POSIXACLS diff --git a/libntfs-3g/security.c b/libntfs-3g/security.c index ef036af..f7085cc 100644 --- a/libntfs-3g/security.c +++ b/libntfs-3g/security.c @@ -4466,55 +4466,75 @@ int ntfs_set_ntfs_attrib(ntfs_inode *ni, /* - * Open $Secure once for all + * Open the volume's security descriptor index ($Secure) + * * returns zero if it succeeds - * non-zero if it fails. This is not an error (on NTFS v1.x) + * non-zero if it fails and the NTFS version is at least v3.x */ - - int ntfs_open_secure(ntfs_volume *vol) { ntfs_inode *ni; - int res; + ntfs_index_context *sii; + ntfs_index_context *sdh; - res = -1; - vol->secure_ni = (ntfs_inode*)NULL; - vol->secure_xsii = (ntfs_index_context*)NULL; - vol->secure_xsdh = (ntfs_index_context*)NULL; - if (vol->major_ver >= 3) { - /* make sure this is a genuine $Secure inode 9 */ - ni = ntfs_pathname_to_inode(vol, NULL, "$Secure"); - if (ni && (ni->mft_no == 9)) { - vol->secure_reentry = 0; - vol->secure_xsii = ntfs_index_ctx_get(ni, - sii_stream, 4); - vol->secure_xsdh = ntfs_index_ctx_get(ni, - sdh_stream, 4); - if (ni && vol->secure_xsii && vol->secure_xsdh) { - vol->secure_ni = ni; - res = 0; - } - } + if (vol->secure_ni) /* Already open? */ + return 0; + + ni = ntfs_pathname_to_inode(vol, NULL, "$Secure"); + if (!ni) + goto err; + + /* Verify that $Secure has the expected inode number. */ + if (ni->mft_no != FILE_Secure) { + errno = EINVAL; + goto err_close_ni; } - return (res); + + /* Allocate the needed index contexts. */ + sii = ntfs_index_ctx_get(ni, sii_stream, 4); + if (!sii) + goto err_close_ni; + + sdh = ntfs_index_ctx_get(ni, sdh_stream, 4); + if (!sdh) + goto err_close_sii; + + vol->secure_ni = ni; + vol->secure_xsii = sii; + vol->secure_xsdh = sdh; + return 0; + +err_close_sii: + ntfs_index_ctx_put(sii); +err_close_ni: + ntfs_inode_close(ni); +err: + /* Failing on NTFS versions before 3.x is expected */ + if (vol->major_ver < 3) + return 0; + ntfs_log_perror("error opening $Secure"); + return -1; } /* - * Final cleaning - * Allocated memory is freed to facilitate the detection of memory leaks + * Close the volume's security descriptor index ($Secure) */ - -void ntfs_close_secure(struct SECURITY_CONTEXT *scx) +void ntfs_close_secure(ntfs_volume *vol) { - ntfs_volume *vol; - - vol = scx->vol; if (vol->secure_ni) { ntfs_index_ctx_put(vol->secure_xsii); ntfs_index_ctx_put(vol->secure_xsdh); ntfs_inode_close(vol->secure_ni); - + vol->secure_ni = NULL; } +} + +/* + * Destroy a security context + * Allocated memory is freed to facilitate the detection of memory leaks + */ +void ntfs_destroy_security_context(struct SECURITY_CONTEXT *scx) +{ ntfs_free_mapping(scx->mapping); free_caches(scx); } @@ -5333,7 +5353,6 @@ struct SECURITY_API *ntfs_initialize_file_security(const char *device, scx->vol->secure_flags = 0; /* accept no mapping and no $Secure */ ntfs_build_mapping(scx,(const char*)NULL,TRUE); - ntfs_open_secure(vol); } else { if (scapi) free(scapi); @@ -5365,7 +5384,7 @@ BOOL ntfs_leave_file_security(struct SECURITY_API *scapi) ok = FALSE; if (scapi && (scapi->magic == MAGIC_API) && scapi->security.vol) { vol = scapi->security.vol; - ntfs_close_secure(&scapi->security); + ntfs_destroy_security_context(&scapi->security); free(scapi); if (!ntfs_umount(vol, 0)) ok = TRUE; diff --git a/libntfs-3g/volume.c b/libntfs-3g/volume.c index 4861d2f..7c74a10 100644 --- a/libntfs-3g/volume.c +++ b/libntfs-3g/volume.c @@ -74,6 +74,7 @@ #include "cache.h" #include "realpath.h" #include "misc.h" +#include "security.h" const char *ntfs_home = "News, support and information: http://tuxera.com\n"; @@ -206,6 +207,7 @@ static int __ntfs_volume_release(ntfs_volume *v) ntfs_error_set(&err); } + ntfs_close_secure(v); ntfs_free_lru_caches(v); free(v->vol_name); free(v->upcase); @@ -1234,6 +1236,11 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags) ntfs_log_perror("Failed to close $AttrDef"); goto error_exit; } + + /* Open $Secure. */ + if (ntfs_open_secure(vol)) + goto error_exit; + /* * Check for dirty logfile and hibernated Windows. * We care only about read-write mounts. diff --git a/src/lowntfs-3g.c b/src/lowntfs-3g.c index 08529a4..a91d123 100644 --- a/src/lowntfs-3g.c +++ b/src/lowntfs-3g.c @@ -3852,7 +3852,7 @@ static void ntfs_close(void) / ctx->seccache->head.p_reads % 10); } } - ntfs_close_secure(&security); + ntfs_destroy_security_context(&security); } if (ntfs_umount(ctx->vol, FALSE)) @@ -4363,10 +4363,6 @@ int main(int argc, char *argv[]) #ifdef HAVE_SETXATTR /* extended attributes interface required */ ctx->vol->efs_raw = ctx->efs_raw; #endif /* HAVE_SETXATTR */ - /* JPA open $Secure, (whatever NTFS version !) */ - /* to initialize security data */ - if (ntfs_open_secure(ctx->vol) && (ctx->vol->major_ver >= 3)) - failed_secure = "Could not open file $Secure"; if (!ntfs_build_mapping(&ctx->security,ctx->usermap_path, (ctx->vol->secure_flags & ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL))) diff --git a/src/ntfs-3g.c b/src/ntfs-3g.c index 640cfc4..2578fef 100644 --- a/src/ntfs-3g.c +++ b/src/ntfs-3g.c @@ -3651,7 +3651,7 @@ static void ntfs_close(void) / ctx->seccache->head.p_reads % 10); } } - ntfs_close_secure(&security); + ntfs_destroy_security_context(&security); } if (ntfs_umount(ctx->vol, FALSE)) @@ -4168,10 +4168,6 @@ int main(int argc, char *argv[]) #ifdef HAVE_SETXATTR /* extended attributes interface required */ ctx->vol->efs_raw = ctx->efs_raw; #endif /* HAVE_SETXATTR */ - /* JPA open $Secure, (whatever NTFS version !) */ - /* to initialize security data */ - if (ntfs_open_secure(ctx->vol) && (ctx->vol->major_ver >= 3)) - failed_secure = "Could not open file $Secure"; if (!ntfs_build_mapping(&ctx->security,ctx->usermap_path, (ctx->vol->secure_flags & ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL))) -- 2.9.0 ------------------------------------------------------------------------------ What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports.http://sdm.link/zohodev2dev _______________________________________________ ntfs-3g-devel mailing list ntfs-3g-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ntfs-3g-devel