From: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
To: "Дмитрий Леонтьев" <dm.leontiev7@gmail.com>
Cc: linux-kernel@vger.kernel.org, Jiri Kosina <jkosina@suse.cz>,
dleontie@amd.com, Andrew Morton <akpm@linux-foundation.org>,
Al Viro <viro@zeniv.linux.org.uk>
Subject: Re: procfs does not return error code when file name is already in use
Date: Fri, 26 Oct 2012 10:22:19 -0200 [thread overview]
Message-ID: <20121026122219.GC17909@oc0268524204.ibm.com> (raw)
In-Reply-To: <CA+JonM0vrXtGzhv44o5rOH-3z_BuU52=Nu8WmiMz5m1=ENZ9HA@mail.gmail.com>
On Fri, Oct 26, 2012 at 01:57:43PM +0400, Дмитрий Леонтьев wrote:
> I'm working a kernel module, and one of my tasks is to disallow a
> process to open my character device(/dev/xxx) more than once. I tried
> to solve this problem by creating /proc/apu directory, and creating a
> /proc/xxx/{pid} file for when process opens /dev/xxx. This file will
> act as per-process mutex, and provide a way to control resource usage.
>
> Then, I investigated,if procfs acts as I expect from it, and found
> that procfs checks file names for uniqueness, but does not return an
> error when I add two files with same name. Instead, it posts silly
> messages to kernel log, and adds new entry as if nothing happened.
> This is a vulnerability:
>
> Let we have 2 modules A and B trying to create file /proc/foo on load,
> and removing it on unload. Load A, Load B, unload B. at step 3 B
> removed /proc/foo owned by A, and /proc/foo created by B remains
> accessible from userspace.
>
> My patch fixes this behaviour: proc_register will return -EEXIST when
> file name is in use, and refuse to add a duplicate.
>
> ----start of patch for fs/proc/generic.c---------------------------------------
> --- generic.c.orig 2012-10-25 22:20:05.196606263 +0400
> +++ generic.c 2012-10-25 22:13:49.556955392 +0400
> @@ -554,45 +554,51 @@ static const struct inode_operations pro
>
You just push a lot of code a level deep, without any need, and don't
handle your error path properly.
> static int proc_register(struct proc_dir_entry * dir, struct
> proc_dir_entry * dp)
> {
> + int errorcode=-EAGAIN;
You have lots of coding style problems like this. Please use spaces
before and after =, like this:
int errorcode = -EAGAIN;
> unsigned int i;
> struct proc_dir_entry *tmp;
>
> i = get_inode_number();
> - if (i == 0)
> - return -EAGAIN;
You must use release_inode_number if you go into the error path. If you
want to distinguish between this error path and the -EEXIST one, you'd
better keep this as it is. Just return the error here and don't do the
extra indentation.
> - dp->low_ino = i;
> -
> - if (S_ISDIR(dp->mode)) {
> - if (dp->proc_iops == NULL) {
> - dp->proc_fops = &proc_dir_operations;
> - dp->proc_iops = &proc_dir_inode_operations;
> + if (i != 0)
> + {
> + errorcode=0;
> +
> + dp->low_ino = i;
> +
> + if (S_ISDIR(dp->mode)) {
> + if (dp->proc_iops == NULL) {
> + dp->proc_fops = &proc_dir_operations;
> + dp->proc_iops = &proc_dir_inode_operations;
> + }
> + dir->nlink++;
Same here. You must undo the extra link, if you go through an error
path.
> + } else if (S_ISLNK(dp->mode)) {
> + if (dp->proc_iops == NULL)
> + dp->proc_iops = &proc_link_inode_operations;
> + } else if (S_ISREG(dp->mode)) {
> + if (dp->proc_fops == NULL)
> + dp->proc_fops = &proc_file_operations;
> + if (dp->proc_iops == NULL)
> + dp->proc_iops = &proc_file_inode_operations;
> }
> - dir->nlink++;
> - } else if (S_ISLNK(dp->mode)) {
> - if (dp->proc_iops == NULL)
> - dp->proc_iops = &proc_link_inode_operations;
> - } else if (S_ISREG(dp->mode)) {
> - if (dp->proc_fops == NULL)
> - dp->proc_fops = &proc_file_operations;
> - if (dp->proc_iops == NULL)
> - dp->proc_iops = &proc_file_inode_operations;
> - }
>
> - spin_lock(&proc_subdir_lock);
> + spin_lock(&proc_subdir_lock);
>
> - for (tmp = dir->subdir; tmp; tmp = tmp->next)
> - if (strcmp(tmp->name, dp->name) == 0) {
> - WARN(1, KERN_WARNING "proc_dir_entry '%s/%s' already registered\n",
> - dir->name, dp->name);
> - break;
Please, keep the warning. In my experience, it points out to real bugs
in new code.
> + for (tmp = dir->subdir; tmp; tmp = tmp->next)
> + {
> + if (strcmp(tmp->name, dp->name) == 0) {
> + errorcode=-EEXIST;
> + break;
> + }
> }
> -
> - dp->next = dir->subdir;
> - dp->parent = dir;
> - dir->subdir = dp;
> - spin_unlock(&proc_subdir_lock);
> -
> - return 0;
> + if(!errorcode)
> + {
> + dp->next = dir->subdir;
> + dp->parent = dir;
> + dir->subdir = dp;
> + }
> + spin_unlock(&proc_subdir_lock);
> + }
> + return errorcode;
> }
>
> static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
> ----end of patch---------------------------------------
>
> Regards
> Dmitry
> --
Regards.
Cascardo.
prev parent reply other threads:[~2012-10-26 12:22 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-26 9:57 procfs does not return error code when file name is already in use Дмитрий Леонтьев
2012-10-26 10:06 ` Jiri Kosina
2012-10-26 12:05 ` Thadeu Lima de Souza Cascardo
2012-10-26 11:03 ` Al Viro
2012-10-26 12:22 ` Thadeu Lima de Souza Cascardo [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20121026122219.GC17909@oc0268524204.ibm.com \
--to=cascardo@linux.vnet.ibm.com \
--cc=akpm@linux-foundation.org \
--cc=dleontie@amd.com \
--cc=dm.leontiev7@gmail.com \
--cc=jkosina@suse.cz \
--cc=linux-kernel@vger.kernel.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox