* [PATCH v2 0/4] pstore: Initial use of cleanup.h
@ 2023-12-05 18:26 Kees Cook
2023-12-05 18:26 ` [PATCH v2 1/4] pstore: inode: Convert kfree() usage to __free(kfree) Kees Cook
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Kees Cook @ 2023-12-05 18:26 UTC (permalink / raw)
To: Guilherme G. Piccoli; +Cc: Kees Cook, Tony Luck, linux-kernel, linux-hardening
Hi,
Mostly as practice for myself, I rewrote a bunch of the error handling
paths in pstore to use the new cleanup.h routines. I'm enjoying this part:
"44 insertions(+), 65 deletions(-)"
It also passes basic testing. :)
-Kees
v2: do not add a global iput macro
v1: https://lore.kernel.org/lkml/20231202211535.work.571-kees@kernel.org/
Kees Cook (4):
pstore: inode: Convert kfree() usage to __free(kfree)
pstore: inode: Convert mutex usage to guard(mutex)
pstore: inode: Use __free(pstore_iput) for inode allocations
pstore: inode: Use cleanup.h for struct pstore_private
fs/pstore/inode.c | 109 +++++++++++++++++++---------------------------
1 file changed, 44 insertions(+), 65 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/4] pstore: inode: Convert kfree() usage to __free(kfree)
2023-12-05 18:26 [PATCH v2 0/4] pstore: Initial use of cleanup.h Kees Cook
@ 2023-12-05 18:26 ` Kees Cook
2023-12-05 18:26 ` [PATCH v2 2/4] pstore: inode: Convert mutex usage to guard(mutex) Kees Cook
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Kees Cook @ 2023-12-05 18:26 UTC (permalink / raw)
To: Guilherme G. Piccoli; +Cc: Kees Cook, Tony Luck, linux-hardening, linux-kernel
Mostly as an example to myself, replace a simple allocation pattern with
the automatic kfree cleanup features now exposed by cleanup.h.
Cc: "Guilherme G. Piccoli" <gpiccoli@igalia.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-hardening@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
fs/pstore/inode.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index d41c20d1b5e8..20f3452c8196 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -23,6 +23,7 @@
#include <linux/pstore.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
+#include <linux/cleanup.h>
#include "internal.h"
@@ -64,7 +65,7 @@ static void free_pstore_private(struct pstore_private *private)
static void *pstore_ftrace_seq_start(struct seq_file *s, loff_t *pos)
{
struct pstore_private *ps = s->private;
- struct pstore_ftrace_seq_data *data;
+ struct pstore_ftrace_seq_data *data __free(kfree) = NULL;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
@@ -72,13 +73,10 @@ static void *pstore_ftrace_seq_start(struct seq_file *s, loff_t *pos)
data->off = ps->total_size % REC_SIZE;
data->off += *pos * REC_SIZE;
- if (data->off + REC_SIZE > ps->total_size) {
- kfree(data);
+ if (data->off + REC_SIZE > ps->total_size)
return NULL;
- }
-
- return data;
+ return_ptr(data);
}
static void pstore_ftrace_seq_stop(struct seq_file *s, void *v)
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/4] pstore: inode: Convert mutex usage to guard(mutex)
2023-12-05 18:26 [PATCH v2 0/4] pstore: Initial use of cleanup.h Kees Cook
2023-12-05 18:26 ` [PATCH v2 1/4] pstore: inode: Convert kfree() usage to __free(kfree) Kees Cook
@ 2023-12-05 18:26 ` Kees Cook
2023-12-05 18:26 ` [PATCH v2 3/4] pstore: inode: Use __free(pstore_iput) for inode allocations Kees Cook
2023-12-05 18:26 ` [PATCH v2 4/4] pstore: inode: Use cleanup.h for struct pstore_private Kees Cook
3 siblings, 0 replies; 5+ messages in thread
From: Kees Cook @ 2023-12-05 18:26 UTC (permalink / raw)
To: Guilherme G. Piccoli; +Cc: Kees Cook, Tony Luck, linux-hardening, linux-kernel
Replace open-coded mutex handling with cleanup.h guard(mutex) and
scoped_guard(mutex, ...).
Cc: "Guilherme G. Piccoli" <gpiccoli@igalia.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-hardening@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
fs/pstore/inode.c | 76 +++++++++++++++++++----------------------------
1 file changed, 31 insertions(+), 45 deletions(-)
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 20f3452c8196..0d89e0014b6f 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -180,25 +180,21 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
{
struct pstore_private *p = d_inode(dentry)->i_private;
struct pstore_record *record = p->record;
- int rc = 0;
if (!record->psi->erase)
return -EPERM;
/* Make sure we can't race while removing this file. */
- mutex_lock(&records_list_lock);
- if (!list_empty(&p->list))
- list_del_init(&p->list);
- else
- rc = -ENOENT;
- p->dentry = NULL;
- mutex_unlock(&records_list_lock);
- if (rc)
- return rc;
-
- mutex_lock(&record->psi->read_mutex);
- record->psi->erase(record);
- mutex_unlock(&record->psi->read_mutex);
+ scoped_guard(mutex, &records_list_lock) {
+ if (!list_empty(&p->list))
+ list_del_init(&p->list);
+ else
+ return -ENOENT;
+ p->dentry = NULL;
+ }
+
+ scoped_guard(mutex, &record->psi->read_mutex)
+ record->psi->erase(record);
return simple_unlink(dir, dentry);
}
@@ -290,19 +286,16 @@ static struct dentry *psinfo_lock_root(void)
{
struct dentry *root;
- mutex_lock(&pstore_sb_lock);
+ guard(mutex)(&pstore_sb_lock);
/*
* Having no backend is fine -- no records appear.
* Not being mounted is fine -- nothing to do.
*/
- if (!psinfo || !pstore_sb) {
- mutex_unlock(&pstore_sb_lock);
+ if (!psinfo || !pstore_sb)
return NULL;
- }
root = pstore_sb->s_root;
inode_lock(d_inode(root));
- mutex_unlock(&pstore_sb_lock);
return root;
}
@@ -317,19 +310,19 @@ int pstore_put_backend_records(struct pstore_info *psi)
if (!root)
return 0;
- mutex_lock(&records_list_lock);
- list_for_each_entry_safe(pos, tmp, &records_list, list) {
- if (pos->record->psi == psi) {
- list_del_init(&pos->list);
- rc = simple_unlink(d_inode(root), pos->dentry);
- if (WARN_ON(rc))
- break;
- d_drop(pos->dentry);
- dput(pos->dentry);
- pos->dentry = NULL;
+ scoped_guard(mutex, &records_list_lock) {
+ list_for_each_entry_safe(pos, tmp, &records_list, list) {
+ if (pos->record->psi == psi) {
+ list_del_init(&pos->list);
+ rc = simple_unlink(d_inode(root), pos->dentry);
+ if (WARN_ON(rc))
+ break;
+ d_drop(pos->dentry);
+ dput(pos->dentry);
+ pos->dentry = NULL;
+ }
}
}
- mutex_unlock(&records_list_lock);
inode_unlock(d_inode(root));
@@ -353,20 +346,20 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
if (WARN_ON(!inode_is_locked(d_inode(root))))
return -EINVAL;
- rc = -EEXIST;
+ guard(mutex)(&records_list_lock);
+
/* Skip records that are already present in the filesystem. */
- mutex_lock(&records_list_lock);
list_for_each_entry(pos, &records_list, list) {
if (pos->record->type == record->type &&
pos->record->id == record->id &&
pos->record->psi == record->psi)
- goto fail;
+ return -EEXIST;
}
rc = -ENOMEM;
inode = pstore_get_inode(root->d_sb);
if (!inode)
- goto fail;
+ return -ENOMEM;
inode->i_mode = S_IFREG | 0444;
inode->i_fop = &pstore_file_operations;
scnprintf(name, sizeof(name), "%s-%s-%llu%s",
@@ -394,7 +387,6 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
d_add(dentry, inode);
list_add(&private->list, &records_list);
- mutex_unlock(&records_list_lock);
return 0;
@@ -402,8 +394,6 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
free_pstore_private(private);
fail_inode:
iput(inode);
-fail:
- mutex_unlock(&records_list_lock);
return rc;
}
@@ -449,9 +439,8 @@ static int pstore_fill_super(struct super_block *sb, void *data, int silent)
if (!sb->s_root)
return -ENOMEM;
- mutex_lock(&pstore_sb_lock);
- pstore_sb = sb;
- mutex_unlock(&pstore_sb_lock);
+ scoped_guard(mutex, &pstore_sb_lock)
+ pstore_sb = sb;
pstore_get_records(0);
@@ -466,17 +455,14 @@ static struct dentry *pstore_mount(struct file_system_type *fs_type,
static void pstore_kill_sb(struct super_block *sb)
{
- mutex_lock(&pstore_sb_lock);
+ guard(mutex)(&pstore_sb_lock);
WARN_ON(pstore_sb && pstore_sb != sb);
kill_litter_super(sb);
pstore_sb = NULL;
- mutex_lock(&records_list_lock);
+ guard(mutex)(&records_list_lock);
INIT_LIST_HEAD(&records_list);
- mutex_unlock(&records_list_lock);
-
- mutex_unlock(&pstore_sb_lock);
}
static struct file_system_type pstore_fs_type = {
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 3/4] pstore: inode: Use __free(pstore_iput) for inode allocations
2023-12-05 18:26 [PATCH v2 0/4] pstore: Initial use of cleanup.h Kees Cook
2023-12-05 18:26 ` [PATCH v2 1/4] pstore: inode: Convert kfree() usage to __free(kfree) Kees Cook
2023-12-05 18:26 ` [PATCH v2 2/4] pstore: inode: Convert mutex usage to guard(mutex) Kees Cook
@ 2023-12-05 18:26 ` Kees Cook
2023-12-05 18:26 ` [PATCH v2 4/4] pstore: inode: Use cleanup.h for struct pstore_private Kees Cook
3 siblings, 0 replies; 5+ messages in thread
From: Kees Cook @ 2023-12-05 18:26 UTC (permalink / raw)
To: Guilherme G. Piccoli; +Cc: Kees Cook, Tony Luck, linux-hardening, linux-kernel
Simplify error path for failures where "inode" needs to be freed.
Cc: "Guilherme G. Piccoli" <gpiccoli@igalia.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-hardening@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
fs/pstore/inode.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 0d89e0014b6f..a27764341079 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -35,6 +35,8 @@ static LIST_HEAD(records_list);
static DEFINE_MUTEX(pstore_sb_lock);
static struct super_block *pstore_sb;
+DEFINE_FREE(pstore_iput, struct inode *, if (_T) iput(_T))
+
struct pstore_private {
struct list_head list;
struct dentry *dentry;
@@ -337,7 +339,7 @@ int pstore_put_backend_records(struct pstore_info *psi)
int pstore_mkfile(struct dentry *root, struct pstore_record *record)
{
struct dentry *dentry;
- struct inode *inode;
+ struct inode *inode __free(pstore_iput) = NULL;
int rc = 0;
char name[PSTORE_NAMELEN];
struct pstore_private *private, *pos;
@@ -369,7 +371,7 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
private = kzalloc(sizeof(*private), GFP_KERNEL);
if (!private)
- goto fail_inode;
+ return -ENOMEM;
dentry = d_alloc_name(root, name);
if (!dentry)
@@ -384,7 +386,7 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
inode_set_mtime_to_ts(inode,
inode_set_ctime_to_ts(inode, record->time));
- d_add(dentry, inode);
+ d_add(dentry, no_free_ptr(inode));
list_add(&private->list, &records_list);
@@ -392,8 +394,6 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
fail_private:
free_pstore_private(private);
-fail_inode:
- iput(inode);
return rc;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 4/4] pstore: inode: Use cleanup.h for struct pstore_private
2023-12-05 18:26 [PATCH v2 0/4] pstore: Initial use of cleanup.h Kees Cook
` (2 preceding siblings ...)
2023-12-05 18:26 ` [PATCH v2 3/4] pstore: inode: Use __free(pstore_iput) for inode allocations Kees Cook
@ 2023-12-05 18:26 ` Kees Cook
3 siblings, 0 replies; 5+ messages in thread
From: Kees Cook @ 2023-12-05 18:26 UTC (permalink / raw)
To: Guilherme G. Piccoli; +Cc: Kees Cook, Tony Luck, linux-hardening, linux-kernel
Simplify error path when "private" needs to be freed.
Cc: "Guilherme G. Piccoli" <gpiccoli@igalia.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-hardening@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
fs/pstore/inode.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index a27764341079..d0d9bfdad30c 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -63,6 +63,7 @@ static void free_pstore_private(struct pstore_private *private)
}
kfree(private);
}
+DEFINE_FREE(pstore_private, struct pstore_private *, free_pstore_private(_T));
static void *pstore_ftrace_seq_start(struct seq_file *s, loff_t *pos)
{
@@ -340,9 +341,8 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
{
struct dentry *dentry;
struct inode *inode __free(pstore_iput) = NULL;
- int rc = 0;
char name[PSTORE_NAMELEN];
- struct pstore_private *private, *pos;
+ struct pstore_private *private __free(pstore_private) = NULL, *pos;
size_t size = record->size + record->ecc_notice_size;
if (WARN_ON(!inode_is_locked(d_inode(root))))
@@ -358,7 +358,6 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
return -EEXIST;
}
- rc = -ENOMEM;
inode = pstore_get_inode(root->d_sb);
if (!inode)
return -ENOMEM;
@@ -375,7 +374,7 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
dentry = d_alloc_name(root, name);
if (!dentry)
- goto fail_private;
+ return -ENOMEM;
private->dentry = dentry;
private->record = record;
@@ -388,13 +387,9 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
d_add(dentry, no_free_ptr(inode));
- list_add(&private->list, &records_list);
+ list_add(&(no_free_ptr(private))->list, &records_list);
return 0;
-
-fail_private:
- free_pstore_private(private);
- return rc;
}
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-12-05 18:26 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-05 18:26 [PATCH v2 0/4] pstore: Initial use of cleanup.h Kees Cook
2023-12-05 18:26 ` [PATCH v2 1/4] pstore: inode: Convert kfree() usage to __free(kfree) Kees Cook
2023-12-05 18:26 ` [PATCH v2 2/4] pstore: inode: Convert mutex usage to guard(mutex) Kees Cook
2023-12-05 18:26 ` [PATCH v2 3/4] pstore: inode: Use __free(pstore_iput) for inode allocations Kees Cook
2023-12-05 18:26 ` [PATCH v2 4/4] pstore: inode: Use cleanup.h for struct pstore_private Kees Cook
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).