SD卡加密—内核修改

bio_vec[i]对应一个block或者一个page
bio面向page或者面向块,详见第五次汇报里讲解的。
1struct bio {
sector_t bi_sector; /* device address in 512 byte
……
void *backup;//结构体末尾加变量backup空指针,作用?
};
struct page {
unsigned long flags; /* Atomic flags, some possibly
……
unsigned long buffer_flag;//page结构体末尾加入这个标记,标记函数是否经过了mpage_readpages
};
buffer_flag识别函数是否经过了mpage_readpages函数。只有读文件数据经过该函数,读取目录和挂载过程不经过该函数,这个特点可以在generic_make_request()函数和回调函数中用于分辨本次IO是读文件IO(加解密),还是读取文件夹的IO(不加密))。
1 void generic_make_request(struct bio *bio)
{
struct bio_list bio_list_on_stack;
 
/********************/
 
 
unsigned char *address_bf;
int major;
int i,j;
unsigned long rw_flag;
unsigned long int tt,nvec;
unsigned long buffer_flag=9;
address_bf=page_address(bio->bi_io_vec[0].bv_page);
address_bf=address_bf+bio->bi_io_vec[0].bv_offset;
major=MAJOR(bio->bi_bdev->bd_dev);//求设备号,SD卡设备号179
tt=bio->bi_sector;
nvec=bio->bi_vcnt;
rw_flag=(bio->bi_rw)&WRITE;
if(major==179)
{
printk("\ngeneric: %s:  tt:%ld  nvec:%ld", (rw_flag)?"write":"read", tt, nvec);
for(i=0;i<nvec;i++)
{
if (bio->bi_io_vec[i].bv_page->buffer_flag == 2) //该标记在函数?中,赋值2,只有读文件时经过该函数,读目录(区)不经过。满足条件,说明是读文件,则将标记改为3.
bio->bi_io_vec[i].bv_page->buffer_flag = 3;
buffer_flag = bio->bi_io_vec[i].bv_page->buffer_flag;
 
printk("\n%s buffer_flag:%ld", (rw_flag)?"write":"read", buffer_flag);
}
}
 
    if((major==179)&&(rw_flag)&&(buffer_flag==3))   //(tt>1000)
  {
  for(i=0;i<bio->bi_io_vec[0].bv_len/512;i++)
  {
  printk("before write:%d\n", address_bf[i*512]);
for(j=0;j<512;j++)
{
address_bf[j+i*512]^=0xff;
}
}
}
/************************/
 
if (current->bio_list) {
/* make_request is active */
………
………
}
2mpage机制的回调函数:
static void mpage_end_io(struct bio *bio, int err)//bio->bi_io_vec数组对应各个数据段,每个数据段对应pages(非mpage机制每个数据段对应一个块),如:bio->bi_io_vec[0]对应一页。
{
const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
unsigned long buffer_flag=6;
 
do {
struct page *page = bvec->bv_page;
 
if (--bvec >= bio->bi_io_vec)
prefetchw(&bvec->bv_page->flags);
if (bio_data_dir(bio) == READ) {
if (uptodate) {
/******************/
struct bio_vec *bvecx;
unsigned char *address_bf;
unsigned long int tt;
 
bvecx=bvec+1;
buffer_flag = bvecx->bv_page->buffer_flag;
address_bf=page_address(bvecx->bv_page);
address_bf=address_bf+bvecx->bv_offset;
 
 
tt = bio->bi_sector;//这个扇区号为绝对扇区号,generic_make_request()等函数里的bio中的扇区号为从分区表起始的相对扇区号。本特点本项目中没有用到。
printk("\nmpage_end_io:tt:%ld\n",tt);
if (buffer_flag == 3){   //(tt>1000)//buffer_flag == 3说明为读取文件,而不是目录,
//yy=tt;
int i,j;
 
int major=MAJOR(bio->bi_bdev->bd_dev);
printk("\nmajor:%d",major);
if(major==179)
{
 
for(i=0;i<bvecx->bv_len/512;i++)
{
printk("\nmpage_end_io:before read:%d\n", address_bf[i*512]);
    for(j=0;j<512;j++)
{
 address_bf[j+i*512]^=0xff;
  }
}
  }
}
/******************/
SetPageUptodate(page);
3异步读回调函数: static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
{
unsigned long flags;
struct buffer_head *first;
struct buffer_head *tmp;
struct page *page;
int page_uptodate = 1;
unsigned long buffer_flag=8;
 
BUG_ON(!buffer_async_read(bh));
 
page = bh->b_page;
buffer_flag = page->buffer_flag;
if (uptodate) {
/****************/
unsigned char *tmp1;
tmp1=(unsigned char*)bh->b_data;
unsigned long int tt = (bh->b_blocknr * (bh->b_size >> 9));
printk("\nend_buffer_async_read:tt:%ld",tt);
 
if (buffer_flag == 3){   //(tt>1000)
int i,j;
int major=MAJOR(bh->b_bdev->bd_dev);
if(major==179)
{
 
for(i=0;i<((bh->b_size)/512);i++)
{
printk("\nasync before read :%d", tmp1[i*512]);
    for(j=0;j<512;j++)
{
//printk(KERN_INFO "The original data is:%d\n", tmp1[j+i*512]);
 tmp1[j+i*512]^=0xff;
 //printk(KERN_INFO "The encryption data is%d\n", tmp1[j+i*512]);
  }
}
 }
}
/*****************/
set_buffer_uptodate(bh);
4同步读回调函数:static void __end_buffer_read_notouch(struct buffer_head *bh, int uptodate)//(end_buffer_sync_read调用该函数)
{
if (uptodate) {
/**********/
unsigned char *tmp1;
tmp1=(unsigned char*)bh->b_data;
unsigned long int tt = (bh->b_blocknr * (bh->b_size >> 9));
unsigned long buffer_flag=7;
 
printk("\nnotouch:tt:%ld",tt);
buffer_flag = bh->b_page->buffer_flag;
 
if (buffer_flag == 3){   //(tt>1000)
int i,j;
int major=MAJOR(bh->b_bdev->bd_dev);
if(major==179)
{
 
for(i=0;i<((bh->b_size)/512);i++)
{
printk("\nnotouch:before read:%d", tmp1[i*512]);
    for(j=0;j<512;j++)
{
//printk(KERN_INFO "The original data is:%d\n", tmp1[j+i*512]);
 tmp1[j+i*512]^=0xff;
 //printk(KERN_INFO "The encryption data is%d\n", tmp1[j+i*512]);
  }
}
 }
}
/*************/
 
set_buffer_uptodate(bh);
} else {
/* This happens, due to failed READA attempts. */
clear_buffer_uptodate(bh);
}
 
unlock_buffer(bh);
}
5触屏读取文件经过该函数,开发板通过USB连接电脑则不通过这个函数。所以用电脑读不出手机SD卡上的数据。
int mpage_readpages(struct address_space *mapping, struct list_head *pages,
unsigned nr_pages, get_block_t get_block)
{
struct bio *bio = NULL;
unsigned page_idx;
sector_t last_block_in_bio = 0;
struct buffer_head map_bh;
unsigned long first_logical_block = 0;
struct blk_plug plug;
 
blk_start_plug(&plug);
 
map_bh.b_state = 0;
map_bh.b_size = 0;
for (page_idx = 0; page_idx < nr_pages; page_idx++) {
struct page *page = list_entry(pages->prev, struct page, lru);
 
prefetchw(&page->flags);
list_del(&page->lru);
if (!add_to_page_cache_lru(page, mapping,
page->index, GFP_KERNEL)) {
printk("\nmpage_readpages !add_to..");
page->buffer_flag = 2;
bio = do_mpage_readpage(bio, page,
nr_pages - page_idx,
&last_block_in_bio, &map_bh,
&first_logical_block,
get_block);
}
page_cache_release(page);
}
BUG_ON(!list_empty(pages));
if (bio)
{
printk("\nmpage_readpages if(bio)");
mpage_bio_submit(READ, bio);
}
blk_finish_plug(&plug);
return 0;
}
6 触屏写入文件经过该函数,创建目录不经过该函数,所以创建文件夹不加密,从而达到只对SD卡文件数据进行加密的目的。
static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
      void *data)
{
struct mpage_data *mpd = data;
struct bio *bio = mpd->bio;
struct address_space *mapping = page->mapping;
struct inode *inode = page->mapping->host;
const unsigned blkbits = inode->i_blkbits;
unsigned long end_index;
const unsigned blocks_per_page = PAGE_CACHE_SIZE >> blkbits;
sector_t last_block;
sector_t block_in_file;
sector_t blocks[MAX_BUF_PER_PAGE];
unsigned page_block;
unsigned first_unmapped = blocks_per_page;
struct block_device *bdev = NULL;
int boundary = 0;
sector_t boundary_block = 0;
struct block_device *boundary_bdev = NULL;
int length;
struct buffer_head map_bh;
loff_t i_size = i_size_read(inode);
int ret = 0;
 
printk("\n__mpage_writepage\n");
page->buffer_flag = 2;
 
if (page_has_buffers(page)) {
struct buffer_head *head = page_buffers(page);
struct buffer_head *bh = head;
 
/* If they're all mapped and dirty, do it */
page_block = 0;
do {
BUG_ON(buffer_locked(bh));
if (!buffer_mapped(bh)) {
/*
        ………
        ……
 
confused:
if (bio)
bio = mpage_bio_submit(WRITE, bio);
 
if (mpd->use_writepage) {
ret = mapping->a_ops->writepage(page, wbc);
} else {
ret = -EAGAIN;
goto out;
}
/*
 * The caller has a ref on the inode, so *mapping is stable
 */
mapping_set_error(mapping, ret);
out:
mpd->bio = bio;
return ret;
}
 
7static void do_generic_file_read(struct file *filp, loff_t *ppos,
read_descriptor_t *desc, read_actor_t actor)
{
………
readpage:
/*
 * A previous I/O error may have been due to temporary
 * failures, eg. multipath errors.
 * PG_error will be set again if readpage fails.
 */
ClearPageError(page);
/* Start the actual read. The read will unlock the page. */
/**yyx***/
page->buffer_flag = 1;
error = mapping->a_ops->readpage(filp, page);
 
if (unlikely(error)) {
if (error == AOP_TRUNCATED_PAGE) {
}
 
 
针对:写入SD卡后,立即读取,读出内容为乱码问题。

 

 

1、修改部分代码:红色字体为修改部分

static void mpage_end_io(s  truct bio *bio, int err)//bio->bi_io_vec数组对应各个数据段,每个数据段对应pages(非mpage机制每个数据段对应一个块),如:bio->bi_io_vec[0]对应一页。

{

       const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);

       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;

       unsigned long buffer_flag=6;

       int i,j;                                

       int major=MAJOR(bio->bi_bdev->bd_dev);//求出主设备号

                           

    int nvec;

       do {

              struct page *page = bvec->bv_page;

 

              if (--bvec >= bio->bi_io_vec)

                     prefetchw(&bvec->bv_page->flags);

              if (bio_data_dir(bio) == READ) {

                     if (uptodate) {

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

                            struct bio_vec *bvecx;

                            unsigned char *address_bf;//

                            unsigned long int tt;//

                           

                            bvecx=bvec+1;

                            buffer_flag = bvecx->bv_page->buffer_flag;//page页的自定义的标记位buffer_flag

                           

                            //printk("\n1111\n");

                            address_bf=page_address(bvecx->bv_page);//求出页的起始地址

                            address_bf=address_bf+bvecx->bv_offset;//页起始地址加上偏移值求出读地址

                            //printk("\n22222\n");

                            //struct buffer_head *bh;

                            //bh=bio->bi_private;

                            //printk("\n33333\n");

                            //unsigned char *tmp1;

                            //tmp1=(unsigned char*)bh->b_data;

                           

                            tt = bio->bi_sector;///这个扇区号为绝对扇区号,generic_make_request()等函数里的bio中的扇区号为从分区表起始的相对扇区号。本特点本项目中没有用到。

                            printk("\nmpage_end_io:tt:%ld\n",tt);

                           

                            if (buffer_flag == 3){   //buffer_flag是自己在page中定义的一个项,用于区分读写的是普通文件还是文件目录表,分区表之类的

 

                                   if(major==179)//major是179,就是针对的是SD卡

                                   {

             

                                          for(i=0;i<bvecx->bv_len/512;i++)//bvecx->bv_len代表一个字段的长度,一个 扇区是512字节,表示有多少个扇区

                                          {

                                                 printk("before read:%d\n", address_bf[i*512]);

                                                 for(j=0;j<512;j++)

                                                 {

                                                         address_bf[j+i*512]^=0xff;//针对每个扇区的每个字节按位取反(相当于加密)

                                                 }

                                          }

                                   }

                            }

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

                            SetPageUptodate(page);

                     } else {

                            ClearPageUptodate(page);

                            SetPageError(page);

                     }

                     unlock_page(page);

              } else { /* bio_data_dir(bio) == WRITE */在这部分是针对写返回的操作

             

                     struct bio_vec *bvecx;

                     unsigned char *address_bf;

                    

                     bvecx=bvec+1;

                     buffer_flag = bvecx->bv_page->buffer_flag;//

                     address_bf=page_address(bvecx->bv_page);//

                     address_bf=address_bf+bvecx->bv_offset;//

            if(major==179)

             

                     {nvec=bio->bi_vcnt;

                     //printk("\nmajor");

                     //printk("\ngeneric: %s:  tt:%ld  nvec:%ld", (rw_flag)?"write":"read", tt, nvec);

                     for(i=0;i<nvec;i++)//每个bio中段个数

                            {    

                                   if(i>1)

                                   {

                                   printk("%d mpage nvec= \n",i);

 

                                   }

                                   //buffer_flag=bio->bi_io_vec[i].bv_page->buffer_flag;

                                   buffer_flag = bio->bi_io_vec[i].bv_page->buffer_flag;

 

                                   //address_bf=page_address(bio->bi_io_vec[i].bv_page);

                                   //address_bf=address_bf+bio->bi_io_vec[i].bv_offset;

                                   if (buffer_flag == 3)//如果是写SD卡返回,在generic_make_request中,如果执行generic_make_request函数,则将此标记位置为3,此位置判断是否为3,如果是3的话,就判定他执行了generic_make_request函数

                                   {     //bio->bi_io_vec[i].bv_page->buffer_flag = 3;

                                          //buffer_flag = bio->bi_io_vec[i].bv_page->buffer_flag;

                                          address_bf=page_address(bio->bi_io_vec[i].bv_page);//

                                          address_bf=address_bf+bio->bi_io_vec[i].bv_offset;

                                          memcpy(address_bf,bio->bi_io_vec[i].bv_data_address,bio->bi_io_vec[i].bv_len);//参照generic_make_request函数,在generic_make_request函数中,针对要操作的缓冲区,又申请了一个缓冲区,将原先的明文备份,此处是将备份的明文重新拷贝到原先的缓冲区中,使系统感觉不到加密,

                                          kfree(bio->bi_io_vec[i].bv_data_address);//将申请的用于备份的缓冲区释放掉

                                          printk("\nnvec\n");

                                          printk("mpage success\n");

                                   }

                                   printk("\n end_ion   success");

      

                            }

                     }

                    

      

             

                     if (!uptodate) {

                            SetPageError(page);

                            if (page->mapping)

                                   set_bit(AS_EIO, &page->mapping->flags);

                     }

                     end_page_writeback(page);

              }

       } while (bvec >= bio->bi_io_vec);

       bio_put(bio);

}

void generic_make_request(struct bio *bio)

{

       struct bio_list bio_list_on_stack;

 

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

 

       unsigned char *address_bf;

       int major;

       int i,k,j;

       unsigned long rw_flag;

       unsigned long int tt,nvec;

       unsigned long buffer_flag=9;

       //unsigned long check_flag;

       //struct buffer_head *bh_fyk;

      

      

       major=MAJOR(bio->bi_bdev->bd_dev);//求出设备的主设备号

       tt=bio->bi_sector;

       nvec=bio->bi_vcnt;

       rw_flag=(bio->bi_rw)&WRITE;

 

       if(major==179)//主设备号是179是SD卡

       {    

              printk("\ngeneric: %s:  tt:%ld  nvec:%ld", (rw_flag)?"write":"read", tt, nvec);

              for(i=0;i<nvec;i++)

              {    

                     if (bio->bi_io_vec[i].bv_page->buffer_flag == 2)

                     {

                            bio->bi_io_vec[i].bv_page->buffer_flag = 3;//该标记在函数?中,赋值2,只有读文件时经过该函数,读目录(区)不经过。满足条件,说明是读文件,则将标记改为3.

                     }

                     buffer_flag = bio->bi_io_vec[i].bv_page->buffer_flag;//置新的标志位

                     if (rw_flag)//如果是写

                     {

                            address_bf=page_address(bio->bi_io_vec[i].bv_page);

                            address_bf=address_bf+bio->bi_io_vec[i].bv_offset;//求出地址 

                            printk("\naddress_bf:%08x, page:%08x, bio:%08x\n", (unsigned int)address_bf, (unsigned int)bio->bi_io_vec[i].bv_page, (unsigned int)bio);

                            if (buffer_flag==3)//注意:如果是写SD卡的话(前面已经有major和rw_flag进行判断),统一将buffer_flag置为3

                            {

                                   //address_bf=page_address(bio->bi_io_vec[i].bv_page);

                                  //address_bf=address_bf+bio->bi_io_vec[i].bv_offset;

                                   bio->bi_io_vec[i].bv_data_address=kmalloc(bio->bi_io_vec[i].bv_len,GFP_KERNEL);//申请一块缓冲区

                                   memcpy(bio->bi_io_vec[i].bv_data_address,address_bf,bio->bi_io_vec[i].bv_len);//将明文保存在地址为bio->bi_io_vec[i].bv_data_address的缓冲区中

                                for(k=0;k<bio->bi_io_vec[i].bv_len/512;k++)//具体到扇区中

                                {

                                  printk("before write:%d\n", address_bf[k*512]);

                                  for(j=0;j<512;j++)

                                          {

                                                 address_bf[j+k*512]^=0xff;//char型数据,8位。0xff

                                          }

                                }              

                            }    

                     }

           }

              //printk("\n%s buffer_flag:%ld", (rw_flag)?"write":"read", buffer_flag);

       }    

 

注:修改的结构体如下:

struct bio_vec {

       struct page      *bv_page;

       unsigned int    bv_len;

       unsigned int    bv_offset;

       char *bv_data_address;//此处为新加的结构体项,用于保存新申请的缓冲区的指针

};

struct page {

       unsigned long flags;              /* Atomic flags, some possibly

                                    * updated asynchronously */

       atomic_t _count;           /* Usage count, see below. */

       union {

              atomic_t _mapcount;     /* Count of ptes mapped in mms,

                                    * to show when page is mapped

                                    * & limit reverse map searches.

                                    */

              struct {           /* SLUB */

                     u16 inuse;

                     u16 objects;

              };

       };

       union {

           struct {

              unsigned long private;           /* Mapping-private opaque data:

                                           * usually used for buffer_heads

                                           * if PagePrivate set; used for

                                           * swp_entry_t if PageSwapCache;

                                           * indicates order in the buddy

                                           * system if PG_buddy is set.

                                           */

              struct address_space *mapping;     /* If low bit clear, points to

                                           * inode address_space, or NULL.

                                           * If page mapped as anonymous

                                           * memory, low bit is set, and

                                           * it points to anon_vma object:

                                           * see PAGE_MAPPING_ANON below.

                                           */

           };

#if USE_SPLIT_PTLOCKS

           spinlock_t ptl;

#endif

           struct kmem_cache *slab; /* SLUB: Pointer to slab */

           struct page *first_page;    /* Compound tail pages */

       };

       union {

              pgoff_t index;        /* Our offset within mapping. */

              void *freelist;        /* SLUB: freelist req. slab lock */

       };

       struct list_head lru;        /* Pageout list, eg. active_list

                                    * protected by zone->lru_lock !

                                    */

       /*

        * On machines where all RAM is mapped into kernel address space,

        * we can simply calculate the virtual address. On machines with

        * highmem some memory is mapped into kernel virtual memory

        * dynamically, so we need a place to store that address.

        * Note that this field could be 16 bits on x86 ... ;)

        *

        * Architectures with slow multiplication can define

        * WANT_PAGE_VIRTUAL in asm/page.h

        */

#if defined(WANT_PAGE_VIRTUAL)

       void *virtual;                /* Kernel virtual address (NULL if

                                      not kmapped, ie. highmem) */

#endif /* WANT_PAGE_VIRTUAL */

#ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS

       unsigned long debug_flags;   /* Use atomic bitops on this */

#endif

 

#ifdef CONFIG_KMEMCHECK

       /*

        * kmemcheck wants to track the status of each byte in a page; this

        * is a pointer to such a status block. NULL if not tracked.

        */

       void *shadow;

#endif

       unsigned long buffer_flag;//新加一个项,用于判断读写的文件类型,以及对于后面操作的一个标记位

 

};

buffer_flag识别函数是否经过了mpage_readpages函数。只有读文件数据经过该函数,读取目录和挂载过程不经过该函数,这个特点可以在generic_make_request()函数和回调函数中用于分辨本次IO是读文件IO(加解密),还是读取文件夹的IO(不加密))。

 

posted @ 2014-10-20 09:13  twdreamer  阅读(1002)  评论(0编辑  收藏  举报