云原生之容器安全实践

概述

云原生(Cloud Native)是一套技术体系和方法论,它由2个词组成,云(Cloud)和原生(Native)。云(Cloud)表示应用程序位于云中,而不是传统的数据中心;原生(Native)表示应用程序从设计之初即考虑到云的环境,原生为云而设计,在云上以最佳状态运行,充分利用和发挥云平台的弹性和分布式优势。

云原生的代表技术包括容器、服务网格(Service Mesh)、微服务(Microservice)、不可变基础设施和声明式API。更多对于云原生的介绍请参考CNCF/Foundation。

图1 云原生安全技术沙盘(Security View)

笔者将“云原生安全”抽象成如上图所示的技术沙盘。自底向上看,底层从硬件安全(可信环境)到宿主机安全 。将容器编排技术(Kubernetes等)看作云上的“操作系统”,它负责自动化部署、扩缩容、管理应用等。在它之上由微服务、Service Mesh、容器技术(Docker等)、容器镜像(仓库)组成。它们之间相辅相成,以这些技术为基础构建云原生安全。

我们再对容器安全做一层抽象,又可以看作构建时安全(Build)、部署时安全(Deployment)、运行时安全(Runtime)。

在美团内部,镜像安全由容器镜像分析平台保障。它以规则引擎的形式运营监管容器镜像,默认规则支持对镜像中Dockerfile、可疑文件、敏感权限、敏感端口、基础软件漏洞、业务软件漏洞以及CIS和NIST的最佳实践做检查,并提供风险趋势分析,同时它确保部分构建时安全。

容器在云原生架构下由容器编排技术(例如Kubernetes)负责部署,部署安全同时也与上文提及的容器编排安全有交集。

运行安全管控交由HIDS负责(可参考《保障IDC安全:分布式HIDS集群架构设计》一文)。本文所讨论的范畴也属于运行安全之一,主要解决以容器逃逸为模型构建的风险(在本文中,若无特殊说明,容器指代Docker)。

对于安全实施准则,我们将其分为三个阶段:

  • 攻击前:裁剪攻击面,减少对外暴露的攻击面(本文涉及的场景关键词:隔离);
  • 攻击时:降低攻击成功率(本文涉及的场景关键词:加固);
  • 攻击后:减少攻击成功后攻击者所能获取的有价值的信息、数据以及增加留后门的难度等。

近些年,数据中心的基础架构逐渐从传统的虚拟化(例如KVM+QEMU架构)转向容器化(Kubernetes+Docker架构),但“逃逸”始终都是企业要在这2种架构下所面对的最严峻的安全问题,同时它也是容器风险中最具代表性的安全问题。笔者将以容器逃逸为切入点,从攻击者角度(容器逃逸)到防御者角度(缓解容器逃逸)来阐述容器安全的实践,从而缓解容器风险。

容器风险

容器提供了将应用程序的代码、配置、依赖项打包到单个对象的标准方法。容器建立在两项关键技术之上:Linux Namespace和Linux Cgroups。

Namespace创建一个近乎隔离的用户空间,并为应用程序提供系统资源(文件系统、网络栈、进程和用户ID)。Cgroup强制限制硬件资源,如CPU、内存、设备和网络等。

容器和VM不同之处在于,VM模拟硬件系统,每个VM都可以在独立环境中运行OS。管理程序模拟CPU、内存、存储、网络资源等,这些硬件可由多个VM共享多次。

图2 容器攻击面(Container Attack Surface)

容器一共有7个攻击面:Linux Kernel、Namespace/Cgroups/Aufs、Seccomp-bpf、Libs、Language VM、User Code、Container(Docker) engine。

笔者以容器逃逸为风险模型,提炼出3个攻击面:

  1. Linux内核漏洞;
  2. 容器自身;
  3. 不安全部署(配置)。

1. Linux内核漏洞

容器的内核与宿主内核共享,使用Namespace与Cgroups这两项技术,使容器内的资源与宿主机隔离,所以Linux内核产生的漏洞能导致容器逃逸。

内核提权VS容器逃逸

通用Linux内核提权方法论

  • 信息收集:收集一切对写exploit有帮助的信息。 如:内核版本,需要确定攻击的内核是什么版本? 这个内核版本开启了哪些加固配置? 还需知道在写shellcode的时候会调用哪些内核函数?这时候就需要查询内核符号表,得到函数地址。 还可从内核中得到一些对编写利用有帮助的地址信息、结构信息等等。

  • 触发阶段:触发相关漏洞,控制RIP,劫持内核代码路径,简而言之,获取在内核中任意执行代码的能力。

  • 布置shellcode:在编写内核exploit代码的时候,需要找到一块内存来存放我们的shellcode 。 这块内存至少得满足两个条件:

    • 第一:在触发漏洞时,我们要劫持代码路径,必须保证代码路径可以到达存放shellcode的内存。
    • 第二:这块内存是可以被执行的,换句话说,存放shellcode的这块内存具有可执行权限。
  • 执行阶段

    • 第一:获取高于当前用户的权限,一般我们都是直接获取root权限,毕竟它是Linux中的最高权限,也就是执行我们的shellcode。
    • 第二:保证内核稳定,不能因为我们需要提权而破坏原来内核的代码路径、内核结构、内核数据等等,而导致内核崩溃。这样的话,即使得到root权限也没有太大的意义。

简而言之,收集对编写exploit有帮助的信息,然后触发漏洞去执行特权代码,达到提权的效果。

图3 容器逃逸简易模型(Container Escape Model)

容器逃逸和内核提权只有细微的差别,需要突破namespace的限制。将高权限的namespace赋到exploit进程的task_struct中。这部分的详细技术细节不在本文讨论范围内,笔者未来会抽空再写一篇关于容器逃逸的技术文章,详细介绍该相关技术的细节。

经典的Dirty CoW

笔者以Dirty CoW漏洞来说明Linux漏洞导致的容器逃逸。漏洞虽老,奈何太过经典。写到这,笔者不禁想问:多年过去,目前国内外各大厂,Dirty Cow漏洞的存量机器修复率是多少?

在Linux内核的内存子系统处理私有只读内存映射的写时复制(Copy-on-Write,CoW)机制的方式中发现了一个竞争冲突。一个没有特权的本地用户,可能会利用此漏洞获得对其他情况下只读内存映射的写访问权限,从而增加他们在系统上的特权,这就是知名的Dirty CoW漏洞。

Dirty CoW漏洞的逃逸的实现思路和上述的思路不太一样,采取Overwrite vDSO技术。

vDSO(Virtual Dynamic Shared Object)是内核为了减少内核与用户空间频繁切换,提高系统调用效率而设计的机制。它同时映射在内核空间以及每一个进程的虚拟内存中,包括那些以root权限运行的进程。通过调用那些不需要上下文切换(context switching)的系统调用可以加快这一步骤(定位vDSO)。vDSO在用户空间(userspace)映射为R/X,而在内核空间(kernelspace)则为R/W。这允许我们在内核空间修改它,接着在用户空间执行。又因为容器与宿主机内核共享,所以可以直接使用这项技术逃逸容器。

利用步骤如下:

  1. 获取vDSO地址,在新版的glibc中可以直接调用getauxval()函数获取;
  2. 通过vDSO地址找到clock_gettime()函数地址,检查是否可以hijack;
  3. 创建监听socket;
  4. 触发漏洞,Dirty CoW是由于内核内存管理系统实现CoW时产生的漏洞。通过条件竞争,把握好在恰当的时机,利用CoW的特性可以将文件的read-only映射该为write。子进程不停地检查是否成功写入。父进程创建二个线程,ptrace_thread线程向vDSO写入shellcode。madvise_thread线程释放vDSO映射空间,影响ptrace_thread线程CoW的过程,产生条件竞争,当条件触发就能写入成功。
  5. 执行shellcode,等待从宿主机返回root shell,成功后恢复vDSO原始数据。

2. 容器自身

我们先简单的看一下Docker的架构图:

图4 Docker架构图

Docker本身由Docker(Docker Client)和Dockerd(Docker Daemon)组成。但从Docker 1.11开始,Docker不再是简单的通过Docker Dameon来启动,而是集成许多组件,包括containerd、runc等等。

Docker Client是Docker的客户端程序,用于将用户请求发送给Dockerd。Dockerd实际调用的是containerd的API接口,containerd是Dockerd和runc之间的一个中间交流组件,主要负责容器运行、镜像管理等。containerd向上为Dockerd提供了gRPC接口,使得Dockerd屏蔽下面的结构变化,确保原有接口向下兼容;向下,通过containerd-shim与runc结合创建及运行容器。更多的相关内容,请参考文末链接runc、containerd、architecture。了解清楚这些之后,我们就可以结合自身的安全经验,从这些组件相互间的通信方式、依赖关系等寻找能导致逃逸的漏洞。

下面我们以Docker中的runc组件所产生的漏洞来说明因容器自身的漏洞而导致的逃逸。

CVE-2019-5736:runc - container breakout vulnerability

runc在使用文件系统描述符时存在漏洞,该漏洞可导致特权容器被利用,造成容器逃逸以及访问宿主机文件系统;攻击者也可以使用恶意镜像,或修改运行中的容器内的配置来利用此漏洞。

  • 攻击方式1:(该途径需要特权容器)运行中的容器被入侵,系统文件被恶意篡改 ==> 宿主机运行docker exec命令,在该容器中创建新进程 ==> 宿主机runc被替换为恶意程序 ==> 宿主机执行docker run/exec 命令时触发执行恶意程序;

  • 攻击方式2:(该途径无需特权容器)docker run命令启动了被恶意修改的镜像 ==> 宿主机runc被替换为恶意程序 ==> 宿主机运行docker run/exec命令时触发执行恶意程序。

当runc在容器内执行新的程序时,攻击者可以欺骗它执行恶意程序。通过使用自定义二进制文件替换容器内的目标二进制文件来实现指回runc二进制文件。

如果目标二进制文件是/bin/bash,可以用指定解释器的可执行脚本替换#!/proc/self/exe。因此,在容器内执行/bin/bash,/proc/self/exe的目标将被执行,将目标指向runc二进制文件。

然后攻击者可以继续写入/proc/self/exe目标,尝试覆盖主机上的runc二进制文件。这里需要使用O_PATH flag打开/proc/self/exe文件描述符,然后以O_WRONLY flag 通过/proc/self/fd/ 重新打开二进制文件,并且用单独的一个进程不停地写入。当写入成功时,runc会退出。

3. 不安全部署(配置)

在实际中,我们经常会遇到这种状况:不同的业务会根据自身业务需求提供一套自己的配置,而这套配置并未得到有效的管控审计,使得内部环境变得复杂多样,无形之中又增加了很多风险点。最常见的包括:

  • 特权容器或者以root权限运行容器;
  • 不合理的Capability配置(权限过大的Capability)。

面对特权容器,在容器内简单地执行一下命令,就可以轻松地在宿主机上留下后门:

$ wget https://kernfunny.org/backdoor/rootkit.ko && insmod rootkit.ko

目前在美团内部,我们已经有效地收敛了特权容器问题。

这部分业界已经给出了最佳实践,从宿主机配置、Dockerd配置、容器镜像、Dockerfile、容器运行时等方面保障了安全,更多细节请参考Benchmark/Docker。同时Docker官方已经将其实现成自动化工具(gVisor)。

安全实践

为解决上述部分所阐述的容器逃逸问题,下文将重点从隔离(安全容器)与加固(安全内核)两个角度来进行讨论。

安全容器

安全容器的技术本质就是隔离。gVisor和Kata Container是比较具有代表性的实现方式,目前学术界也在探索基于Intel SGX的安全容器。

简单地说,gVisor是在用户态和内核态之间抽象出一层,封装成API,有点像user-mode kernel,以此实现隔离。Kata Container采用了轻量级的虚拟机隔离,与传统的VM比较类似,但是它实现了无缝集成当前的Kubernetes加Docker架构。我们接着来看gVisor与Kata Container的异同。

Case 1: gVisor

gVisor是用Golang编写的用户态内核,或者说是沙箱技术,它主要实现了大部分的system call。它运行在应用程序和内核之间,为它们提供隔离。gVisor被使用在Google云计算平台的App Engine、Cloud Functions和Cloud ML中。gVisor运行时,是由多个沙箱组成,这些沙箱进程共同覆盖了一个或多个容器。通过拦截从应用程序到主机内核的所有系统调用,并使用用户空间中的Sentry处理它们,gVisor充当guest kernel的角色,且无需通过虚拟化硬件转换,可以将它看做vmm与guest kernel的集合,或是seccomp的增强版。

图5 gVisor架构图(来自gVisor)

Case 2: Kata Container

Kata Container的Container Runtime是用hypervisor ,然后用hardware virtualization实现,如同虚拟机。所以每一个像这样的Kata Container的Pod,都是一个轻量级虚拟机,它拥有完整的Linux内核。所以Kata Container与VM一样能提供强隔离性,但由于它的优化和性能设计,同时也拥有与容器相媲美的敏捷性。

图6 Kata Container 架构图(图片来自Katacontainers.io)

Kata Container在主机上有一个kata-runtime来启动和配置新容器。对于Kata VM中的每个容器,主机上都有相应的Kata Shim。 Kata Shim接收来自客户端的API请求(例如Docker或kubectl),并通过VSock将请求转发给Kata VM内的代理。 Kata容器进一步优化以减少VM启动时间。 使用QEMU的轻量级版本NEMU,删除了约80%的设备和包。 VM-Templating创建运行Kata VM实例的克隆,并与其他新创建的Kata VM共享,这样减少了启动时间和Guest VM内存消耗。 Hotplug功能允许VM使用最少的资源(例如CPU、内存、virtio块)进行引导,并在以后请求时添加其他资源。

gVisor VS Kata Container

在两者之间,笔者更愿选择gVisor,因为gVisor设计上比Kata Container更加的“轻”量级,但gVisor的性能问题始终是一道暂时无法逾越的“天堑”。综合二者的优劣,Kata Container目前更适合企业内部。总体而言,安全容器技术还需做诸多探索,以解决不同企业内部基础架构上面临的各种挑战。

安全内核

众所周知,Android由于其开源特性,不同厂商都维护着自己的Android版本。因为Android内核态代码来自于Linux kernel upstrem,当一个漏洞产生在upstrem内核,安全补丁推送到Google,再从Google下发到各大厂商,最终到终端用户。由于Android生态的碎片化,补丁周期非常之长,使得终端用户的安全,在这过程中始终处于“空窗期”。当我们把目光重新焦距在Linux上,它也同样存在类似的问题。

内核面临的问题

图7 漏洞生命周期(The Vulnerability Life Cycle)

内核补丁

当一个安全漏洞被披露,通常是由漏洞发现者通过Redhat、OpenSuse、Debian等社区反馈或直接提交至上游相关子系统maintainer。在企业内部面临多个不同内核大版本、内核定制化,针对不同版本从上游代码backport相关补丁及制作相关热补丁,定制内核还需对补丁进行二次开发,再升级生产环境内核或Hotfix内核。不仅修复周期过长,而且在修复过程中,人员沟通也存在一定的成本,也拉长了漏洞危险期。在危险期间,我们对于漏洞基本是毫无防护能力的。

内核版本碎片化

内核版本碎片化在任意具备一定规模的公司都是无法避免的问题。随着技术的日新月异,不断迭代,基础架构上的技术栈需要较新版本的内核功能去支持,久而久之就产生内核版本的碎片化。碎片化问题的存在,使得在安全补丁的推送方面,遭遇了很大的挑战。本身补丁还需要做针对性的适配,包括不同版本的内核,并进行测试验证,碎片化使得维护成本也变得十分高昂。最重要的是,由于维护工作量大,必然拉长了测试补丁的时间线。也就是说,暴露在攻击者面前的危险期变得更长,被攻击的可能性也大大增加。

内核版本定制化

同样,因不同公司的基础架构不同、需求不同,导致的定制化内核问题。对于定制化内核,无法简单的通过从上游内核合并补丁,还需对补丁做一些本地化来适配定制化内核。这又拉长了危险期。

解决之道

我们使用安全特性去针对某一类漏洞或是针对某一类利用方式做防御与检测。比如SLAB_FREELIST_HARDENED,针对Double Free类型漏洞做实时检测,且防御overwrite freelist链表,性能损耗仅0.07%(参考upstrem内核源码,commit id: 2482ddec)。当完成所有全部的安全特性,漏洞在被反馈之前和漏洞补丁被及时推送至生产环境前,都无需关心漏洞的细节,就能防御。当然,安全补丁该打还是得打,这里我们主要解决在安全补丁最终落在生产环境过程中,“空窗期”对于漏洞与利用毫无防御能力的问题,同时也可以对0day有一定的检测及防御能力。

实施策略

  1. 已经合并进Linux主线版本的安全特性,如果公司的内核支持该特性,选择开启配置,对开启前后内核做性能测试,分析安全特性原理、行业数据,给出Real World攻击案例(自己写exploit去证明),将报告结论反馈给内核团队。内核团队再做评估,结合安全团队与内核团队双方意见,最终评估落地。

  2. 已经合并进Linux主线版本但未被合并进Redhat的安全特性,可选择从Linux内核主线版本中移植,这点上代码质量上得到了保障,同时社区也做了性能测试,将其合并到公司的内核再做复测。

  3. 未被合并进Linux内核主线版本,从Grsecurity/PaX中做移植,在Grsecurity/PaX的诸多安全特性中,评估选择,选取代码改动少的,收益高的安全特性优先移植。比如改动较少的内核代码又能有效解决某一类的漏洞,再打个比方,Dirty Cow的全量修复可能需要花费1-2年的时间,如果加了某个安全特性,即使未修复也能防御。

内核后话

最后,分享一下笔者眼中较为理想中的状况。当然,我们得根据实际情况“因地制宜”,在不同阶段做出不同的取舍与选择。

  • 将内核团队看成社区,我们向他们提交代码,如同Linux内核社区有RFC(Request for Comment)、Patch Review等,无争议后合并进公司内核。
  • 先挑选实用的安全特性且代码量少的,去移植,去实现,并落地。代码量少意味着对内核代码改动少,出问题的可能性越小,稳定性越高,性能损耗越低。
  • 一年完成几个安全特性,不需要多,1~2个即可,对于内核态的加固,慎重慎重再慎重,譬如国外G家公司数据中心的内核发版前大概需要6~7个月时间做性能、稳定性测试。
  • 需要做到加固某个安全特性后,使用0day或Nday去验证防御效果,且基于该内核跑业务是稳定,性能损耗在可接受范围之内或者可控。每个安全特性需要技术评审。为保障代码质量的问题,找实际的高吞吐以及高并发低延迟的服务器小范围灰度测试,无争议后,再推送给内核团队。
  • 最后,我们还可以通过将安全特性的代码直接提交给Linux内核社区,如果代码有不足的地方也可以和社区协同解决,合并进Linux内核主线代码,从而侧面推动落地。

作者简介

Pray3r,负责美团内部操作系统安全、云原生安全、重大高危漏洞应急响应,长期专注于Linux内核安全及开源软件安全。

参考文献

  • CNCF/Foundation
  • 保障IDC安全:分布式HIDS集群架构设计
  • Dirty Cow
  • runc
  • containerd
  • Docker/Containerd/Architecture
  • OSS-Security
  • Frichetten/CVE-2019-5736-PoC
  • Docker
  • Benchmark/Docker/
  • gVisor.dev
  • Container Isolation at Scale
  • Kata-Containers/Documentation
  • Kernel
  • Redhat
  • Namespaces in operation, part 1: namespaces overview
  • Control groups series by Neil Brown
  • Container-Security
  • Anatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxCon
  • A Short Story: Bypass SMEP on Linux

美团-信息安全部招聘云原生安全工程师/专家

岗位职责:

  1. 云原生(微服务、Service Mesh、容器技术、容器编排技术)安全研究及转化落地;
  2. 对云原生安全有独到见解,能给业务方提供技术支持。

岗位要求:

  1. 熟悉Docker、Kubernetes等云原生技术及其原理,熟悉相关主流的最佳安全实践;
  2. 熟悉Linux操作系统,对操作系统、虚拟化等底层技术有一定了解;
  3. 熟悉使用C/Python/Golang其中一门语言;
  4. 熟悉业界安全攻防动态,追踪最新安全漏洞,能够分析漏洞原理和实现POC编写;
  5. 有良好的沟通和团队协作能力,能够推动业务落地相关的安全要求和解决方案;
  6. 良好的英文阅读能力。

加分项:

  1. 熟悉Linux内核;
  2. 熟悉开源社区;
  3. 在渗透测试,漏洞挖掘,代码审计等安全领域至少有一个方面能力突出;
  4. 发表过有深度的技术Paper或独立挖掘过知名开源应用/大型厂商高危漏洞经历。

如有意向,请发送简历:tech@meituan.com(备注:云安全)

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

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

相关文章

领域应用 | HiTA知识图谱 “药品-适应证”图谱数据发布!

本文转载自公众号:OMAHA联盟。2019年8月,OMAHA对HiTA知识图谱服务平台(kg.omaha.org.cn)进行了更新,同步发布了医学知识图谱表达模型(schema)。2019年9月17日,首次发布了由OMAHA研发…

主题模型综述:短文本、细粒度、加入先验知识、作者写作偏好、主题内涵随时间的变迁、融入词嵌入特性、语言模型加持

原文链接:https://www.zhihu.com/question/34801598/answer/765580727 主题模型当然有用咯,谁用谁知道!这次我来展示下它的7个“变种”(短文本、细粒度、加入先验知识、作者写作偏好、主题内涵随时间的变迁、融入词嵌入特性、语言模型加持)&a…

完全解析:使用Faiss进行海量特征的相似度匹配

文 | Gemfield源 | 知乎Faiss为稠密向量提供高效相似度搜索和聚类,支持十亿级别向量的搜索,是目前最为成熟的近似近邻搜索库。本文从最基本的特征比对开始讲解,中间详细讲解Faiss的环境配置以及使用步骤,最后落脚到为什么我们需要…

LeetCode 173. 二叉搜索树迭代器(中序遍历)

文章目录1. 题目信息2. 二叉树中序遍历1. 题目信息 实现一个二叉搜索树迭代器。你将使用二叉搜索树的根节点初始化迭代器。 调用 next() 将返回二叉搜索树中的下一个最小的数。 示例: BSTIterator iterator new BSTIterator(root); iterator.next(); // 返…

论文浅尝 | 面向时序知识图谱推理的循环事件网络

论文笔记整理:谭亦鸣,东南大学博士生,研究方向为知识库问答。来源:arXiv (short version accepted at ICLR 2019Workshop on Representation Learning on Graphs and Manifolds)链接:https://arxiv.org/abs/1904.05530…

Android实现炫酷的星空变幻效果

二话不说,先上效果图: 这个图是什么意思呢,有没有看到一直在变颜色啊,有没有很像星云变幻呢,有没有很炫,快来看看怎么实现的吧! 这是我们要被处理的原图,实现方式就是通过不断的改变…

美团配送数据治理实践

大数据时代的到来,让越来越多的企业看到了数据资产的价值。将数据视为企业的重要资产,已经成为业界的一种共识,企业也在快速探索应用场景和商业模式,并开始建设技术平台。 但这里要特别强调一下,如果在大数据“拼图”中…

这可能是你近 2 年发论文最好机会!

几年前如果熟练使用TensorFlow,同时掌握基本的AI算法就可以很容易找到一份高薪的工作,但现在不一样了,AI岗位的要求越来越高,对知识的深度也提出了更高的要求。如果现在一个面试官让你从零推导SVM的Dual、从零实现CRF、推导LDA、设…

LeetCode 671. 二叉树中第二小的节点

文章目录1. 题目信息2. 解题2.1 递归查找2.2 改循环1. 题目信息 给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。如果一个节点有两个子节点的话,那么这个节点的值不大于它的子节点的值。 给出这样的一…

论文浅尝 | 多标签分类中的元学习

论文笔记整理:叶群,浙江大学计算机学院,知识图谱、NLP方向。会议:EMNLP 2019链接:https://arxiv.org/abs/1909.04176Abstract这篇论文首次在多标签分类问题中提出了 meta-learning 的方法,学习weight polic…

从源码角度分析Android系统的异常捕获机制是如何运行的

我们在开发的时候经常会遇到各种异常,当程序遇到异常,便会将异常信息抛到LogCat中,那这个过程是怎么实现的呢? 我们以一个例子开始: import android.app.Activity; import android.os.Bundle;public class MainActivit…

法律规则鬼畜图解||全面易懂的旅游投诉赔偿标准

法律规则鬼畜图解||全面易懂的旅游投诉赔偿标准https://zhuanlan.zhihu.com/p/82878902 执笔人:张宗保律师(联系方式:知乎私信)执业地域:深圳市执业方向:民商事诉讼一、赔偿标准的适用前提只有在旅游者和旅…

美团技术十年:让我们感动的那些人那些事

时光荏苒,美团十岁了,美团技术团队也走过了十个春秋。 2010年3月4日美团网上线的时候,整个公司总共十来人,在一套三居室的民房里起步。其中技术团队只有5个人,现在有4位还在美团。 今天,美团是中国市值第三…

LeetCode 113. 路径总和 II(回溯)

文章目录1. 题目信息2. 解题1. 题目信息 给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 给定如下二叉树,以及目标和 sum 22,5/ \4 8/ / \11 1…

开放开源 | DeepKE:基于深度学习的开源中文关系抽取工具

本文转载自公众号:浙大 KG。作者:余海阳机构:浙江大学代码地址: https://github.com/zjunlp/deepkeOpenKG 发布地址: http://openkg.cn/tool/deepke一、系统简介关系抽取是知识图谱构建的基本子任务之一,它主要面向非结构化的文本…

微前端在美团外卖的实践

背景 微前端是一种利用微件拆分来达到工程拆分治理的方案,可以解决工程膨胀、开发维护困难等问题。随着前端业务场景越来越复杂,微前端这个概念最近被提起得越来越多,业界也有很多团队开始探索实践并在业务中进行了落地。可以看到&#xff0c…

论文浅尝 | Meta Relational Learning: 基于元关系学习的少样本知识图谱推理

本文转载自公众号:浙大KG。 笔记整理:陈名杨,浙江大学在读博士发表会议:EMNLP-2019论文链接:https://arxiv.org/abs/1909.01515开源代码&…

测试集没标签,可以拿来测模型吗?

文:维建编:白鹡鸰背景正常情况下,我们可以用一个带标签的数据集来测试分类器的表现(称之为测试集)。然而,现实中,因为种种因素的制约(标注成本高、标注难度大等 Google:穷…

从0到1 | 手把手教你如何使用哈工大NLP工具——PyLTP!

原文链接:https://flashgene.com/archives/46041.html 本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢. 作者 | 杨秀璋 来源 | CSDN 博客(CSDN id:Eastmount) 【导语】此文是作者基于 Python 构…

美团智能配送系统的运筹优化实战

深入各个产业已经成为互联网目前的主攻方向,线上和线下存在大量复杂的业务约束和多种多样的决策变量,为运筹优化技术提供了用武之地。作为美团智能配送系统最核心的技术之一,运筹优化是如何在美团各种业务场景中进行落地的呢?本文…