/* * pubsys - exploting driverfs for fun and profit * * Copyright (c) 2002 Patrick Mochel * Open Source Development Lab * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * This is a sample subsystem to illustrate how easy it is to latch on to * driverfs and exploit it. It is the 'pub' subsystem. Objects of type 'beer' * can be registered and unregistered with the pub via beer_register and * beer_unregister. * * Every time a beer is registered with the pub subsystem, a directory is * created for it. The pub subsystem could then create files on behalf of * the beer, in the beer's directory. Once the beer has registered, it * can create files for itself in its directory. A second, more robust * example will surely follow. * * Compiled with CFLAGS = -Wall -O2 -fomit-frame-pointer -DMODULE -D__KERNEL__ IDIR = /home/mochel/src/kernel/devel/linux-2.5/include pubsys.o:: pubsys.c $(CC) $(CFLAGS) -I$(IDIR) -c -o $@ $< */ #include #include #include #include #include #include #include static LIST_HEAD(beer_list); static struct driver_dir_entry * pub_dir; struct beer { char * name; struct list_head node; struct module * owner; struct driver_dir_entry * dir; }; int beer_create_file(struct beer * beer, struct driver_file_entry * entry) { int error = -EINVAL; if (beer) error = driverfs_create_file(entry,beer->dir); return error; } void beer_remove_file(struct beer * beer, struct driver_file_entry * entry) { if (beer) driverfs_remove_file(beer->dir,entry); } static int make_one_dir(char * name, struct driver_dir_entry ** dir, struct driver_dir_entry * parent, void * object) { struct driver_dir_entry * d; int error; d = kmalloc(sizeof(struct driver_dir_entry),GFP_KERNEL); if (!d) return -ENOMEM; memset(d,0,sizeof(struct driver_dir_entry)); d->name = name; d->mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO); INIT_LIST_HEAD(&d->files); d->object = object; if (!(error = driverfs_create_dir(d,parent))) *dir = d; else kfree(d); return error; } static int beer_make_dir(struct beer * beer) { return make_one_dir(beer->name,&beer->dir,pub_dir,beer); } static void beer_remove_dir(struct beer * beer) { struct driver_dir_entry * dir = beer->dir; beer->dir = NULL; driverfs_remove_dir(dir); } int beer_register(struct beer * beer) { int error; MOD_INC_USE_COUNT; error = beer_make_dir(beer); if (!error) list_add_tail(&beer->node,&beer_list); else MOD_DEC_USE_COUNT; return error; } void beer_unregister(struct beer * beer) { beer_remove_dir(beer); list_del(&beer->node); MOD_DEC_USE_COUNT; } static int __init pub_init(void) { return make_one_dir("pub",&pub_dir,NULL,NULL); } static void __exit pub_exit(void) { driverfs_remove_dir(pub_dir); } module_init(pub_init); module_exit(pub_exit);