代码之家  ›  专栏  ›  技术社区  ›  Pierre

mysql UDF:fopen=权限被拒绝

  •  2
  • Pierre  · 技术社区  · 16 年前

    :我重新写了这个问题,因为我没有得到答案,我目前正在努力缩小问题的范围。

    我想创造一个 mysql UDF function 检查服务器端是否存在文件。此函数调用“打开/关闭”。即使文件是可读的,它也不起作用。

    #include <mysql.h>
    #include <string.h>
    #include <errno.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    /* The initialization function */
    my_bool fileExists_init(
            UDF_INIT *initid,
            UDF_ARGS *args,
            char *message
            )
      {
      /* check the args */
      if (!(args->arg_count == 1 &&
            args->arg_type[0] == STRING_RESULT
            ))
        {
        strncpy(message,"Bad parameter expected a string",MYSQL_ERRMSG_SIZE);
        return 1;
        }
      initid->maybe_null=1;
      initid->ptr= NULL;
      return 0;
      }
    
    /* The deinitialization function */
    void  fileExists_deinit(UDF_INIT *initid)
        {
        }
    
    #define MAX_RESULT_LENGTH 250
    char *fileExists(
        UDF_INIT *initid, UDF_ARGS *args, char *result,
        unsigned long *length, char *is_null, char *error)
     {
     //bad filename
     if(args->args[0]==NULL  || args->lengths[0]==0 || args->lengths[0] >= FILENAME_MAX )
        {
        strncpy(result,"#BAD_INPUT",MAX_RESULT_LENGTH);
        }
      else
        {
              char  filename[FILENAME_MAX+1];
          int err;
          int in;
          //create a NULL terminated string
          memcpy(filename,args->args[0],args->lengths[0]);
          filename[args->lengths[0]]=0;
          errno=0;
          in=open(filename,O_RDONLY|O_NDELAY);
          err=errno;
          if(in<0)
            {
            snprintf(result,MAX_RESULT_LENGTH,"#ERR:\"%s\":\"%s\".",strerror(err),filename);    
            }
          else
            {
            close(in);
            snprintf(result,MAX_RESULT_LENGTH,"OK:\"%s\".",filename);   
            }
        }
      *length=strlen(result);
      return result;
      }
    

    品牌:

    gcc -Wall -DMYSQL_VERSION -fPIC -shared `mysql_config --cflags` -o `mysql_config --plugindir`/libfileexists.so udffileexists.c  `mysql_config --libs `
    

    测试:

    好的,mysql可以打开一些文件:

    mysql>  create function fileExists RETURNS STRING SONAME 'libfileexists.so'; select fileExists("/etc/mysql/my.cnf"); drop function fileExists;
    Query OK, 0 rows affected (0.00 sec)
    
    +---------------------------------+
    | fileExists("/etc/mysql/my.cnf") |
    +---------------------------------+
    | OK:"/etc/mysql/my.cnf".         | 
    +---------------------------------+
    1 row in set (0.00 sec)
    
    
    
    mysql>  create function fileExists RETURNS STRING SONAME 'libfileexists.so'; select fileExists("/tmp/file.txt"); drop function fileExists;
    Query OK, 0 rows affected (0.00 sec)
    
    +-------------------------------+
    | fileExists("/tmp/file.txt")   |
    +-------------------------------+
    | OK:"/tmp/file.txt".           | 
    +-------------------------------+
    1 row in set (0.00 sec)
    
    Query OK, 0 rows affected (0.00 sec)
    

    好的,没问题,我可以打开()file.txt

    ls -la /tmp 
    drwxrwxrwt 16 root    root       4096 2010-05-28 15:45 .
    -rw-r--r--  1 lindenb lindenb       0 2010-05-28 15:25 file.txt
    

    但是当我想在 :

    ls -la /data
    drwxrwxrwx  4 root    root        4096 2010-05-28 16:11 .
    -rw-r--r--  1 lindenb lindenb        0 2010-05-28 15:25 file.txt
    

    我得到了:

    mysql>  create function fileExists RETURNS STRING SONAME 'libfileexists.so'; select fileExists("/data/file.txt"); drop function fileExists;
    Query OK, 0 rows affected (0.00 sec)
    
    +--------------------------------------------+
    | fileExists("/data/file.txt")               |
    +--------------------------------------------+
    | #ERR:"Permission denied":"/data/file.txt". | 
    +--------------------------------------------+
    1 row in set (0.00 sec)
    

    你知道吗?

    2 回复  |  直到 16 年前
        1
  •  3
  •   Pierre    16 年前

    apparmor .

    解决问题的可能办法 限制已安装的操作 软件可以接受。

    /data/** r,
    

    /etc/apparmor.d/usr.sbin.mysqld
    

    apparmor已重新启动:

    /etc/init.d/apparmor restart
    

        2
  •  0
  •   t0mm13b    16 年前

    你为什么用打开的文件?也许这样做更好:

    char *fileExists(
        UDF_INIT *initid, UDF_ARGS *args, char *result,
        unsigned long *length, char *is_null, char *error)
    {
     //bad filename
     if(args->args[0]==NULL  || args->lengths[0]==0 || args->lengths[0] >= FILENAME_MAX )
     {
       strncpy(result,"#BAD_INPUT",MAX_RESULT_LENGTH);
     }
     else
     {
       char  filename[FILENAME_MAX+1];
       int err;
       int in;
       struct stat statbuffer;
       //create a NULL terminated string
       memcpy(filename,args->args[0],args->lengths[0]);
       filename[args->lengths[0]]=0;
       errno=0;
       if (!stat(filename, &statbuffer)){
         if (S_ISREG(statbuffer.st_mode)){
            snprintf(result,MAX_RESULT_LENGTH,"OK:\"%s\".",filename);
         }else{
            snprintf(result,MAX_RESULT_LENGTH,"#ERR:\"%s\":\"%s\".",strerror(err),filename);
         }
       }else{
         snprintf(result,MAX_RESULT_LENGTH,"#ERR:\"%s\":\"%s\".",strerror(err),filename);
       }
     }
     *length=strlen(result);
     return result;
    }
    

    使用 stat ,这似乎是检查文件是否存在的可靠方法,而且,更容易了解 斯达 功能失效。