代码之家  ›  专栏  ›  技术社区  ›  Sunil Bojanapally

使用linux功能是否禁用LD_PRELOAD

  •  8
  • Sunil Bojanapally  · 技术社区  · 12 年前

    在我的自定义环境中,预加载了一个拦截器库,它运行一个特殊的实现 bind() , connect() 等等。

    我看到的问题是,每当应用程序使用命令显式启用功能时 setcap ,执行应用程序无法预加载拦截器库并调用默认libc 连接() .

    这是预期的行为吗?如果是,禁用的原因是什么 LD_PRELOAD ?

    是否有任何调整或方法可以用来成功预加载启用了功能的库?

    3 回复  |  直到 3 年前
        1
  •  6
  •   Nominal Animal    12 年前

    正如奥利弗·马修斯所回答的那样, LD_PRELOAD 出于安全原因,对setuid二进制文件和具有文件功能的二进制文件都禁用。

    要在预加载库的同时仍启用文件功能,您有两个选项:

    1. 设置预加载的库setuid根目录

      (Linux动态链接器 ld.so 如果库归root所有并标记为set uid,则即使对于启用了setuid/file功能的二进制文件,也会预加载库。)

    2. 使用setuid根包装器

      包装器获得完整的根权限(真实和有效的用户和组ID均为零),并将原始真实用户和组标识存储到例如环境变量中。

      预加载的库有一个构造函数,例如。

      static void my_library_init(void) __attribute__((constructor));
      static void my_library_init(void)
      {
          /* ... */
      }
      

      它在之前自动运行 main() (但可能在其他预加载库中的其他构造函数之后,或者在预加载库所依赖的库中)。

      此构造函数获得所需的功能,可以通过环境变量指定( getenv() , cap_from_text() )或者二进制可执行文件本身( cap_from_file("/proc/self/exe") ).

      构造函数必须临时使用 prctl(PR_SET_KEEPCAPS, 1) 在身份更改时保持能力,并保留 CAP_SETUID CAP_SETGID 能够将身份从root更改为环境变量中指定的用户和组,然后再将其限制为最终的能力集。

    这两种选择都有明显的安全考虑。我建议进行健全性检查(和清理 LD_peload )在预加载的库构造函数中。如果有任何可疑之处,请使用 _exit() 立即中止该过程。

    一般来说,为了简单起见(包括实现和安全问题),我推荐第一种选择,但如果有什么原因不能使用,我也可以为第二种情况提供概念验证代码。(我已经验证了这两个选项在运行3.8.0-27通用x86-64内核、使用ext4文件系统的Ubuntu 12.04.2 LTS上都有效。)

    希望这能有所帮助。

        2
  •  4
  •   Oliver Matthews    12 年前

    是的,这是出于安全原因(请参阅 man sudo ).

    您必须通过在开始时从代码中显式打开库来解决这个问题 main() 使用 dlopen (或通过包裹主要或类似物品)。

        3
  •  0
  •   Rachid K.    1 年前

    要完成以下答案 nominal-animal ,对于选项1(设置预加载库setuid根) manual 指定:

    在安全执行模式下,包含斜线的预加载路径名将被忽略。

    因此,只需指定库的文件名(而不是带斜线的路径名)。

    此外,共享对象仅从标准搜索目录中预加载,并且只有在启用了用户ID模式位的情况下才加载(这并不常见)。

    因此,库必须存储在标准搜索目录集中。

    推荐文章