linux安全体系分析与编程pdf下载,linux内核printk调试(摘录《Linux安全体系分析与编程》)...

这篇博客详细介绍了Linux内核中的syslog函数及其实现,包括读取、清除和管理日志信息的过程。文章涉及了环形缓冲区、权限检查、用户空间与内核空间之间的数据传输等关键概念,并展示了如何处理读取日志时可能出现的各种情况。
摘要由CSDN通过智能技术生成

asmlinkage long sys_syslog(int type, char __user * buf,

int len)

{

return do_syslog(type, buf, len);

}

int do_syslog(int type, char __user *buf, int len)

{

unsigned long i, j, limit, count;

int do_clear = 0;

char c;

int error = 0;

error = security_syslog(type);//检查是否调用这个函数的权限

if (error)

return error;

switch (type) {

case 0:/*关闭日志*/

break;

case 1:/*打开日志*/

break;

case 2:/*读取日志信息*/

error = -EINVAL;

if (!buf || len < 0)

goto out;

error = 0;

if (!len)

goto out;

if (!access_ok(VERIFY_WRITE, buf, len)) {//验证是否有写的权限

error = -EFAULT;

goto out;

}

//当log_start - log_end为0时,表示环形缓冲区无数据可读,把当前进程放入

等待队列log_wait

error = wait_event_interruptible(log_wait,(log_start - log_end));

if (error)

goto out;

i = 0;

spin_lock_irq(&logbuf_lock);

while (!error && (log_start != log_end)

&& i < len) {

c = LOG_BUF(log_start);//从环形缓冲区得到读取位置log_start

log_start++;

spin_unlock_irq(&logbuf_lock);

error = __put_user(c,buf);//将c地址的字符传递到用户空间的buf中

buf++;

i++;

cond_resched();//条件调度,让其他进程有运行时间

spin_lock_irq(&logbuf_lock);

}

spin_unlock_irq(&logbuf_lock);

if (!error)

error = i;

break;

case 4:/*读/清除上一次内核消息*/

do_clear = 1;

/* FALL THRU */

case 3:/*读取上一次内核消息*/

error = -EINVAL;

if (!buf || len < 0)

goto out;

error = 0;

if (!len)//读取长度为0

goto out;

if (!access_ok(VERIFY_WRITE, buf, len)) {//验证有写权限

error = -EFAULT;

goto out;

}

count = len;

if (count > log_buf_len)

count = log_buf_len;

spin_lock_irq(&logbuf_lock);

if (count > logged_chars)// logged_chars是上次读/清除以来产生的日志字符数

count = logged_chars;

if (do_clear)

logged_chars = 0;

limit = log_end;

/* __put_user()可以睡眠,当__put_user睡眠时,printk()可能覆盖写正在

拷贝到用户空间的消息,因此,这些消息被反方向拷贝,将buf覆盖部分的数据重写到buf的起始位置*/

for (i = 0; i < count && !error; i++) {//读取count个字符

j = limit-1-i;

if (j + log_buf_len < log_end)

break;

c = LOG_BUF(j); //从环形缓冲区得到读取位置j

spin_unlock_irq(&logbuf_lock);

//将c位置的字符传递到用户空间的buf中,如果发生错误,将发生错误的c位置给error

error = __put_user(c,&buf[count-1-i]);

cond_resched();

spin_lock_irq(&logbuf_lock);

}

spin_unlock_irq(&logbuf_lock);

if (error)

break;

error = i;

if (i != count) {//表示__put_user没有拷贝完成

int offset = count-error;

/*拷贝期间缓冲区溢出,纠正用户空间缓冲区*/

for (i = 0; i < error; i++) {

if (__get_user(c,&buf[i+offset]) ||

__put_user(c,&buf[i])) {//将覆盖部分的数据

重写到buf的起始位置

error = -EFAULT;

break;

}

cond_resched();

}

}

break;

case 5:/*清除环形缓冲区*/

logged_chars = 0;

break;

case 6:/*关闭向控制台输出消息*/

console_loglevel = minimum_console_loglevel;

break;

case 7:/*开启向控制台输出消息*/

console_loglevel = default_console_loglevel;

break;

case 8:/*设置打印到控制台的日志级别*/

error = -EINVAL;

if (len < 1 || len > 8)

goto out;

if (len < minimum_console_loglevel)

len = minimum_console_loglevel;

console_loglevel = len;

error = 0;

break;

case 9:/*得到日志消息所占缓冲区的大小*/

error = log_end - log_start;

break;

case 10:/*返回环形缓冲区的大小*/

error = log_buf_len;

break;

default:

error = -EINVAL;

break;

}

out:

return error;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值