1 /*
   2  * Copyright (C) 2010 Dan Carpenter.
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU General Public License
   6  * as published by the Free Software Foundation; either version 2
   7  * of the License, or (at your option) any later version.
   8  *
   9  * This program is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  * GNU General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU General Public License
  15  * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
  16  */
  17 
  18 #include "smatch.h"
  19 
  20 static int my_id;
  21 
  22 /* this is stolen from the kernel but it's totally fair use dude...  */
  23 #define __GFP_DMA       (0x01u)
  24 #define __GFP_HIGHMEM   (0x02u)
  25 #define __GFP_DMA32     (0x04u)
  26 #define __GFP_MOVABLE   (0x08u)
  27 #define GFP_ZONEMASK    (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE)
  28 
  29 static void match_alloc(const char *fn, struct expression *expr, void *_arg)
  30 {
  31         int arg_nr = PTR_INT(_arg);
  32         struct expression *arg_expr;
  33         sval_t sval;
  34 
  35         arg_expr = get_argument_from_call_expr(expr->args, arg_nr);
  36         if (!get_value(arg_expr, &sval))
  37                 return;
  38         if (sval.uvalue == 0) /* GFP_NOWAIT */
  39                 return;
  40         if (!(sval.uvalue & ~GFP_ZONEMASK))
  41                 sm_error("no modifiers for allocation.");
  42 }
  43 
  44 void check_gfp_dma(int id)
  45 {
  46         my_id = id;
  47         if (option_project != PROJ_KERNEL)
  48                 return;
  49         add_function_hook("kmalloc", &match_alloc, INT_PTR(1));
  50         add_function_hook("kzalloc", &match_alloc, INT_PTR(1));
  51 }