Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2414593
  • 博文数量: 298
  • 博客积分: 7876
  • 博客等级: 准将
  • 技术积分: 5500
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-23 13:39
文章存档

2013年(2)

2012年(142)

2011年(154)

分类: LINUX

2011-03-24 13:02:48

8)设备访问控制之单用户访问

 

注:所以文章红色字体代表需要特别注意和有问题还未解决的地方,蓝色字体表示需要注意的地方

1.本文所介绍的程序平台

开发板:arm9-mini2440

虚拟机为:Red Hat Enterprise Linux 5

开发板上系统内核版本:linux-2.6.32.2

 

2.程序清单

本次实验程序为国嵌实验和tekkamanninja博客LDD3》代码,本人作了改动和较为详细的注释,如有错误请指出。

 

注意:单用户访问控制有着这样的特点,首先root用户可以直接访问,其次就是其他用户如果是有阻塞的打开设备的话,设备会等到第一个打开设备的用户权限消失(也就是单用户的权限),之后阻塞消失继而让刚刚阻塞的用户继承了权限,以下的arm实验会证明这一点

uonly.c

 

#include

#include

#include

#include

 

#include   /* current and everything */

#include /* printk() */

#include      /* everything... */

#include   /* size_t */

#include

#include

#include

 

struct cdev *singleUIDnb_cdev; 

 

static int singleUIDnb_major = 0;

static int singleUIDnb_minor = 0;

module_param(singleUIDnb_major, int, S_IRUGO);

module_param(singleUIDnb_minor, int, S_IRUGO);

 

DECLARE_COMPLETION(comp);

 

/************************************************************************

 *

 * Next, the device with blocking-open based on uid

 */

 

static int singleUIDnb_count;   /* 设置计数 initialized to 0 by default */

static uid_t singleUIDnb_owner; /* initialized to 0 by default */

static spinlock_t singleUIDnb_lock = SPIN_LOCK_UNLOCKED;

static DECLARE_WAIT_QUEUE_HEAD(singleUIDnb_wait);

 

 

static inline int singleUIDnb_available(void)

{

    return singleUIDnb_count == 0 ||

        singleUIDnb_owner == current->cred->uid ||  /*允许用户*/

        singleUIDnb_owner == current->cred->euid || /*允许执行su命令的用户*/

        capable(CAP_DAC_OVERRIDE);                      /*root用户*/

}

 

 

static int singleUIDnb_open(struct inode *inode, struct file *filp)

{

    spin_lock(&singleUIDnb_lock);

    while (! singleUIDnb_available()) {

printk("<5> failed 1\n");//测试1 测试open失败后的情况

        spin_unlock(&singleUIDnb_lock);

        if (filp->f_flags & O_NONBLOCK) return -EAGAIN;

        if (wait_event_interruptible (singleUIDnb_wait, singleUIDnb_available()))

            return -ERESTARTSYS; /* tell the fs layer to handle it */

        spin_lock(&singleUIDnb_lock);

printk("<5> failed 2\n");//测试2

    }

 

    if (singleUIDnb_count == 0)

        //current->uid 可能只在低版本的内核才能用

        //LINUX2.6.32.2 current->cred->uid

        singleUIDnb_owner = current->cred->uid; /* grab it */

 

    singleUIDnb_count++;

    printk("<5> count : %d\n", singleUIDnb_count);

    spin_unlock(&singleUIDnb_lock);

 

    return 0;          /* success */

}

 

static int singleUIDnb_release(struct inode *inode, struct file *filp)

{

    spin_lock(&singleUIDnb_lock);

    singleUIDnb_count--; /* nothing else */

    spin_unlock(&singleUIDnb_lock);

 

    if (singleUIDnb_count == 0)

        wake_up_interruptible_sync(&singleUIDnb_wait); /* awake other uid's */

    return 0;

}

 

 

ssize_t singleUIDnb_read (struct file *filp, char __user *buf, size_t count, loff_t *pos)

{

    printk(KERN_DEBUG "process %i (%s) going to sleep\n",

            current->pid, current->comm);

    wait_for_completion(&comp);

    printk(KERN_DEBUG "awoken %i (%s)\n", current->pid, current->comm);

    return 0; /* EOF */

}

 

ssize_t singleUIDnb_write (struct file *filp, const char __user *buf, size_t count,

        loff_t *pos)

{

    printk(KERN_DEBUG "process %i (%s) awakening the readers...\n",

            current->pid, current->comm);

    complete(&comp);

    return count; /* succeed, to avoid retrial */

}

 

 

struct file_operations singleUIDnb_fops = {

    .owner = THIS_MODULE,

    .read =  singleUIDnb_read,

    .write = singleUIDnb_write,

    .open =  singleUIDnb_open,

    .release =   singleUIDnb_release,

};

 

 

void singleUIDnb_cleanup(void)

{

 

#if 0

    unregister_chrdev(complete_major, "complete");

#endif

 

//#if 0

    dev_t devno = MKDEV(singleUIDnb_major, singleUIDnb_minor);

    /* Get rid of our char dev entries */

    if (singleUIDnb_cdev) {

        cdev_del(singleUIDnb_cdev);    

        kfree(singleUIDnb_cdev);

    }

    /* cleanup_module is never called if registering failed */

    unregister_chrdev_region(devno,1);

//#endif

 

}

 

 

int singleUIDnb_init(void)

{

#if 0

    int result;

 

    /*

     * Register your major, and accept a dynamic number

     */

    result = register_chrdev(complete_major, "complete", &complete_fops);

    if (result < 0)

        return result;

    if (complete_major == 0)

        complete_major = result; /* dynamic */

    return 0;

#endif

 

//#if 0

    int result,err;

    dev_t dev = 0;

 

    if (singleUIDnb_major) {

        dev = MKDEV(singleUIDnb_major, singleUIDnb_minor);

        result = register_chrdev_region(dev, 1 , "singleUIDnb");

    } else {

        result = alloc_chrdev_region(&dev, singleUIDnb_minor , 1,

                "singleUIDnb");

        singleUIDnb_major = MAJOR(dev);

    }

    if (result < 0) {

        printk(KERN_WARNING "singleUIDnb: can't get major %d\n", singleUIDnb_major);

        return result;

    }

 

        /*

     * allocate the devices -- we can't have them static, as the number

     * can be specified at load time

     */

 

    //complete_cdev = cdev_alloc(); //cdev_alloc() and kmalloc()  are both ok!  use them as you want!

    singleUIDnb_cdev = kmalloc( sizeof(struct cdev), GFP_KERNEL);

 

    if (!singleUIDnb_cdev) {

        result = -ENOMEM;

        goto fail;  /* Make this more graceful */

    }

   

    cdev_init(singleUIDnb_cdev, &singleUIDnb_fops);

 

    singleUIDnb_cdev->owner = THIS_MODULE;

 

    err = cdev_add (singleUIDnb_cdev, dev, 1);

    /* Fail gracefully if need be */

    if (err)

        printk(KERN_NOTICE "Error %d adding singleUIDnb_cdev", err);

 

    return 0; /* succeed */

 

  fail:

    singleUIDnb_cleanup();

    return result;

//#endif

}

 

module_init(singleUIDnb_init);

module_exit(singleUIDnb_cleanup);

 

MODULE_AUTHOR("Tekkaman Ninja");

MODULE_LICENSE("Dual BSD/GPL");

 

singleUID_testr.c

 

#include

#include

#include

#include

#include

 

int main()

{

    int sculltest;

    int code;

   

    if ((sculltest = open("/dev/singleUID",O_RDONLY ))<0) {

        printf("open singleUID error! code=%d \n",sculltest);

        exit(1);

    }

 

        if ((code=read(sculltest , NULL , 0)) < 0) printf("read error! code=%d \n",code);

        else   printf("read ok! code=%d \n",code);

 

    close(sculltest);

 

 exit(0);

}

 

singleUID_testw.c

 

#include

#include

#include

#include

#include

 

int main()

{

    int sculltest;

    int code;

   

    if ((sculltest = open("/dev/singleUID",O_WRONLY ))<0) {

        printf("open singleUID error! code=%d \n",sculltest);

        exit(1);

    }

        if ((code=write(sculltest , NULL , 0)) < 0 ) printf("write error! code=%d \n",code);

        else   printf("write ok! code=%d \n",code);

 

    close(sculltest);

 

  exit(0);

}

 

Arm平台实验:

[root@FriendlyARM /udisk]# insmod uonly.ko

[root@FriendlyARM /udisk]# cat /proc/devices

Character devices:

  1 mem

  4 /dev/vc/0

  4 tty

  5 /dev/tty

  5 /dev/console

  5 /dev/ptmx

  7 vcs

 10 misc

 13 input

 14 sound

 21 sg

 29 fb

 81 video4linux

 89 i2c

 90 mtd

116 alsa

128 ptm

136 pts

180 usb

188 ttyUSB

189 usb_device

204 s3c2410_serial

253 singleUIDnb

254 rtc

 

Block devices:

259 blkext

  7 loop

  8 sd

 31 mtdblock

 65 sd

 66 sd

 67 sd

 68 sd

 69 sd

 70 sd

 71 sd

128 sd

129 sd

130 sd

131 sd

132 sd

133 sd

134 sd

135 sd

179 mmc

[root@FriendlyARM /udisk]# mknod /dev/singleUID c 253 0

[root@FriendlyARM /udisk]# ./singleUID_testr & 这里两个读进程

[root@FriendlyARM /udisk]#  count : 1

 

[root@FriendlyARM /udisk]# ./singleUID_testr &

[root@FriendlyARM /udisk]#  count : 2

 

[root@FriendlyARM /udisk]# su gongzhi 转到另一个账号

[gongzhi@FriendlyARM gongzhi]# cd /udisk/

[gongzhi@FriendlyARM /udisk]# ./singleUID_testw

open singleUID error! code=-1

[gongzhi@FriendlyARM /udisk]# ./singleUID_testr &

失败1 因为read为非阻塞 所以一直等待root用户的权限消失

[gongzhi@FriendlyARM /udisk]#  failed 1

 

[gongzhi@FriendlyARM /udisk]# ./singleUID_testr &

[gongzhi@FriendlyARM /udisk]#  failed 1

 

[gongzhi@FriendlyARM /udisk]# exit

[root@FriendlyARM /udisk]# ./singleUID_testw

 count : 3

write ok! code=0

[root@FriendlyARM /udisk]# read ok! code=0

 

[1] - Done                       ./singleUID_testr

[root@FriendlyARM /udisk]# ps

  PID USER       VSZ STAT COMMAND

    1 root      3068 S    init

    2 root         0 SW   [kthreadd]

    3 root         0 SW   [ksoftirqd/0]

    4 root         0 SW   [events/0]

    5 root         0 SW   [khelper]

   11 root         0 SW   [async/mgr]

  209 root         0 SW   [sync_supers]

  211 root         0 SW   [bdi-default]

  213 root         0 SW   [kblockd/0]

  222 root         0 SW   [khubd]

  228 root         0 SW   [kmmcd]

  244 root         0 SW   [rpciod/0]

  251 root         0 SW   [kswapd0]

  298 root         0 SW   [aio/0]

  302 root         0 SW   [nfsiod]

  306 root         0 SW   [crypto/0]

  413 root         0 SW   [mtdblockd]

  537 root         0 SW   [scsi_eh_0]

  539 root         0 SW   [usb-storage]

  630 root         0 SW   [usbhid_resumer]

  674 root      3068 S    syslogd

  677 root      3328 S    /usr/sbin/inetd

  681 root      1940 S    /usr/sbin/boa

  707 root     13084 S    /opt/Qtopia/bin/qpe

  708 root      3392 S    -/bin/sh

  709 root      3068 S    init

  710 root      3068 S    init

  713 root      3068 S    init

  718 root         0 SW   [flush-31:0]

  728 root      1412 D    ./singleUID_testr

  731 gongzhi   1412 S    ./singleUID_testr

  732 gongzhi   1412 S    ./singleUID_testr

  734 root      3392 R    ps

[root@FriendlyARM /udisk]# ./singleUID_testw

 count : 2

write ok! code=0

[root@FriendlyARM /udisk]# read ok! code=0

 failed 2

 count : 1

 failed 2

 count : 2

 

[2] + Done                       ./singleUID_testr

[root@FriendlyARM /udisk]# ps

  PID USER       VSZ STAT COMMAND

    1 root      3068 S    init

    2 root         0 SW   [kthreadd]

    3 root         0 SW   [ksoftirqd/0]

    4 root         0 SW   [events/0]

    5 root         0 SW   [khelper]

   11 root         0 SW   [async/mgr]

  209 root         0 SW   [sync_supers]

  211 root         0 SW   [bdi-default]

  213 root         0 SW   [kblockd/0]

  222 root         0 SW   [khubd]

  228 root         0 SW   [kmmcd]

  244 root         0 SW   [rpciod/0]

  251 root         0 SW   [kswapd0]

  298 root         0 SW   [aio/0]

  302 root         0 SW   [nfsiod]

  306 root         0 SW   [crypto/0]

  413 root         0 SW   [mtdblockd]

  537 root         0 SW   [scsi_eh_0]

  539 root         0 SW   [usb-storage]

  630 root         0 SW   [usbhid_resumer]

  674 root      3068 S    syslogd

  677 root      3328 S    /usr/sbin/inetd

  681 root      1940 S    /usr/sbin/boa

  707 root     13084 S    /opt/Qtopia/bin/qpe

  708 root      3392 S    -/bin/sh

  709 root      3068 S    init

  710 root      3068 S    init

  713 root      3068 S    init

  718 root         0 SW   [flush-31:0]

  731 gongzhi   1412 D    ./singleUID_testr

  732 gongzhi   1412 D    ./singleUID_testr

  736 root      3392 R    ps

[root@FriendlyARM /udisk]# ./singleUID_testw

 count : 3

write ok! code=0

[root@FriendlyARM /udisk]# read ok! code=0

 

阅读(717) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~