feat(fast-root): get running procs for each pkgs (all RHEL, CentOS, AmazonLinux, Ubuntu, Debian) (#855)

* fix(scan): exec yum-plugin-ps on RHEL6 and 7

* feat(yumps): get affected procs on RHEL6 and RHEL8

* feat(scan): get affected processes for each packages

* tuning

* feat(scan): get running procs for each pkgs on Debian, Ubuntu
This commit is contained in:
Kota Kanbe
2019-07-02 14:55:46 +09:00
committed by GitHub
parent 65e6070e5f
commit f8c0b38716
11 changed files with 402 additions and 405 deletions

View File

@@ -149,6 +149,8 @@ func (o *debian) checkIfSudoNoPasswd() error {
cmds := []string{
"checkrestart",
"stat /proc/1/exe",
"ls -l /proc/1/exe",
"cat /proc/1/maps",
}
if !o.getServerInfo().Mode.IsOffline() {
@@ -262,6 +264,15 @@ func (o *debian) preCure() error {
}
func (o *debian) postScan() error {
if o.getServerInfo().Mode.IsDeep() || o.getServerInfo().Mode.IsFastRoot() {
if err := o.dpkgPs(); err != nil {
err = xerrors.Errorf("Failed to dpkg-ps: %w", err)
o.log.Warnf("err: %+v", err)
o.warns = append(o.warns, err)
// Only warning this error
}
}
if o.getServerInfo().Mode.IsDeep() || o.getServerInfo().Mode.IsFastRoot() {
if err := o.checkrestart(); err != nil {
err = xerrors.Errorf("Failed to scan need-restarting processes: %w", err)
@@ -1109,3 +1120,90 @@ func (o *debian) parseCheckRestart(stdout string) (models.Packages, []string) {
}
return packs, unknownServices
}
func (o *debian) dpkgPs() error {
stdout, err := o.ps()
if err != nil {
return xerrors.Errorf("Failed to ps: %w", err)
}
pidNames := o.parsePs(stdout)
pidLoadedFiles := map[string][]string{}
// for pid, name := range pidNames {
for pid := range pidNames {
stdout := ""
stdout, err = o.lsProcExe(pid)
if err != nil {
o.log.Debugf("Failed to exec /proc/%s/exe err: %s", pid, err)
continue
}
s, err := o.parseLsProcExe(stdout)
if err != nil {
o.log.Debugf("Failed to parse /proc/%s/exe: %s", pid, err)
continue
}
pidLoadedFiles[pid] = append(pidLoadedFiles[pid], s)
stdout, err = o.grepProcMap(pid)
if err != nil {
o.log.Debugf("Failed to exec /proc/%s/maps: %s", pid, err)
continue
}
ss := o.parseGrepProcMap(stdout)
pidLoadedFiles[pid] = append(pidLoadedFiles[pid], ss...)
}
for pid, loadedFiles := range pidLoadedFiles {
o.log.Debugf("dpkg -S %#v", loadedFiles)
pkgNames, err := o.getPkgName(loadedFiles)
if err != nil {
o.log.Debugf("Failed to get package name by file path: %s, err: %s", pkgNames, err)
continue
}
procName := ""
if _, ok := pidNames[pid]; ok {
procName = pidNames[pid]
}
proc := models.AffectedProcess{
PID: pid,
Name: procName,
}
for _, n := range pkgNames {
p, ok := o.Packages[n]
if !ok {
return xerrors.Errorf("pkg not found %s", n)
}
p.AffectedProcs = append(p.AffectedProcs, proc)
o.Packages[p.Name] = p
}
}
return nil
}
func (o *debian) getPkgName(paths []string) (pkgNames []string, err error) {
cmd := "dpkg -S " + strings.Join(paths, " ")
r := o.exec(util.PrependProxyEnv(cmd), noSudo)
if !r.isSuccess(0, 1) {
return nil, xerrors.Errorf("Failed to SSH: %s", r)
}
return o.parseGetPkgName(r.Stdout), nil
}
func (o *debian) parseGetPkgName(stdout string) (pkgNames []string) {
uniq := map[string]struct{}{}
scanner := bufio.NewScanner(strings.NewReader(stdout))
for scanner.Scan() {
line := scanner.Text()
ss := strings.Fields(line)
if len(ss) < 2 || ss[1] == "no" {
continue
}
s := strings.Split(ss[0], ":")[0]
uniq[s] = struct{}{}
}
for n := range uniq {
pkgNames = append(pkgNames, n)
}
return pkgNames
}