Browse code

Apply patches for CVE-2016-3068, CVE-2016-3069, CVE-2016-3105

Change-Id: Ib0678d5623115d2b0e32104eea0293a8fabcb45b
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/1742
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Sharath George

xiaolin-vmware authored on 2016/11/23 12:39:37
Showing 8 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,53 @@
0
+--- a/mercurial/subrepo.py	Wed Mar 16 17:30:26 2016 -0700
1
+@@ -1383,6 +1383,11 @@
2
+         are not supported and very probably fail.
3
+         """
4
+         self.ui.debug('%s: git %s\n' % (self._relpath, ' '.join(commands)))
5
++        if env is None:
6
++            env = os.environ.copy()
7
++        # fix for Git CVE-2015-7545
8
++        if 'GIT_ALLOW_PROTOCOL' not in env:
9
++            env['GIT_ALLOW_PROTOCOL'] = 'file:git:http:https:ssh'
10
+         # unless ui.quiet is set, print git's stderr,
11
+         # which is mostly progress and useful info
12
+         errpipe = None
13
+--- a/tests/test-subrepo-git.t	Wed Mar 16 17:30:26 2016 -0700
14
+@@ -1132,4 +1132,36 @@
15
+   ? s/foobar.orig
16
+   ? s/snake.python.orig
17
+ 
18
++test for Git CVE-2016-3068
19
++  $ hg init malicious-subrepository
20
++  $ cd malicious-subrepository
21
++  $ echo "s = [git]ext::sh -c echo% pwned% >&2" > .hgsub
22
++  $ git init s
23
++  Initialized empty Git repository in $TESTTMP/tc/malicious-subrepository/s/.git/
24
++  $ cd s
25
++  $ git commit --allow-empty -m 'empty'
26
++  [master (root-commit) 153f934] empty
27
+   $ cd ..
28
++  $ hg add .hgsub
29
++  $ hg commit -m "add subrepo"
30
++  $ cd ..
31
++  $ env -u GIT_ALLOW_PROTOCOL hg clone malicious-subrepository malicious-subrepository-protected
32
++  Cloning into '$TESTTMP/tc/malicious-subrepository-protected/s'...
33
++  fatal: transport 'ext' not allowed
34
++  updating to branch default
35
++  cloning subrepo s from ext::sh -c echo% pwned% >&2
36
++  abort: git clone error 128 in s (in subrepo s)
37
++  [255]
38
++
39
++whitelisting of ext should be respected (that's the git submodule behaviour)
40
++  $ env GIT_ALLOW_PROTOCOL=ext hg clone malicious-subrepository malicious-subrepository-clone-allowed
41
++  Cloning into '$TESTTMP/tc/malicious-subrepository-clone-allowed/s'...
42
++  pwned
43
++  fatal: Could not read from remote repository.
44
++  
45
++  Please make sure you have the correct access rights
46
++  and the repository exists.
47
++  updating to branch default
48
++  cloning subrepo s from ext::sh -c echo% pwned% >&2
49
++  abort: git clone error 128 in s (in subrepo s)
50
++  [255]
0 51
new file mode 100644
... ...
@@ -0,0 +1,50 @@
0
+--- a/hgext/convert/git.py	Sun Mar 20 21:52:21 2016 -0700
1
+@@ -11,7 +11,7 @@
2
+ from mercurial.node import hex, nullid
3
+ from mercurial.i18n import _
4
+ 
5
+-from common import NoRepo, commit, converter_source, checktool
6
++from common import NoRepo, commit, converter_source, checktool, commandline
7
+ 
8
+ class submodule(object):
9
+     def __init__(self, path, node, url):
10
+@@ -25,7 +25,7 @@
11
+     def hgsubstate(self):
12
+         return "%s %s" % (self.node, self.path)
13
+ 
14
+-class convert_git(converter_source):
15
++class convert_git(converter_source, commandline):
16
+     # Windows does not support GIT_DIR= construct while other systems
17
+     # cannot remove environment variable. Just assume none have
18
+     # both issues.
19
+@@ -71,6 +71,21 @@
20
+         def gitpipe(self, s):
21
+             return util.popen3('GIT_DIR=%s %s' % (self.path, s))
22
+ 
23
++    def _gitcmd(self, cmd, *args, **kwargs):
24
++        return cmd('--git-dir=%s' % self.path, *args, **kwargs)
25
++
26
++    def gitrun0(self, *args, **kwargs):
27
++        return self._gitcmd(self.run0, *args, **kwargs)
28
++
29
++    def gitrun(self, *args, **kwargs):
30
++        return self._gitcmd(self.run, *args, **kwargs)
31
++
32
++    def gitrunlines0(self, *args, **kwargs):
33
++        return self._gitcmd(self.runlines0, *args, **kwargs)
34
++
35
++    def gitrunlines(self, *args, **kwargs):
36
++        return self._gitcmd(self.runlines, *args, **kwargs)
37
++
38
+     def popen_with_stderr(self, s):
39
+         p = subprocess.Popen(s, shell=True, bufsize=-1,
40
+                              close_fds=util.closefds,
41
+@@ -88,6 +103,7 @@
42
+ 
43
+     def __init__(self, ui, path, revs=None):
44
+         super(convert_git, self).__init__(ui, path, revs=revs)
45
++        commandline.__init__(self, ui, 'git')
46
+ 
47
+         if os.path.isdir(path + "/.git"):
48
+             path += "/.git"
0 49
new file mode 100644
... ...
@@ -0,0 +1,173 @@
0
+--- a/hgext/convert/git.py	Tue Mar 22 17:05:11 2016 -0700
1
+@@ -115,13 +115,13 @@
2
+         if similarity < 0 or similarity > 100:
3
+             raise error.Abort(_('similarity must be between 0 and 100'))
4
+         if similarity > 0:
5
+-            self.simopt = '-C%d%%' % similarity
6
++            self.simopt = ['-C%d%%' % similarity]
7
+             findcopiesharder = ui.configbool('convert', 'git.findcopiesharder',
8
+                                              False)
9
+             if findcopiesharder:
10
+-                self.simopt += ' --find-copies-harder'
11
++                self.simopt.append('--find-copies-harder')
12
+         else:
13
+-            self.simopt = ''
14
++            self.simopt = []
15
+ 
16
+         checktool('git', 'git')
17
+ 
18
+@@ -136,14 +136,14 @@
19
+ 
20
+     def getheads(self):
21
+         if not self.revs:
22
+-            heads, ret = self.gitread('git rev-parse --branches --remotes')
23
+-            heads = heads.splitlines()
24
+-            if ret:
25
++            output, status = self.gitrun('rev-parse', '--branches', '--remotes')
26
++            heads = output.splitlines()
27
++            if status:
28
+                 raise error.Abort(_('cannot retrieve git heads'))
29
+         else:
30
+             heads = []
31
+             for rev in self.revs:
32
+-                rawhead, ret = self.gitread("git rev-parse --verify %s" % rev)
33
++                rawhead, ret = self.gitrun('rev-parse', '--verify', rev)
34
+                 heads.append(rawhead[:-1])
35
+                 if ret:
36
+                     raise error.Abort(_('cannot retrieve git head "%s"') % rev)
37
+@@ -203,7 +203,7 @@
38
+                 self.submodules.append(submodule(s['path'], '', s['url']))
39
+ 
40
+     def retrievegitmodules(self, version):
41
+-        modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules'))
42
++        modules, ret = self.gitrun('show', '%s:%s' % (version, '.gitmodules'))
43
+         if ret:
44
+             # This can happen if a file is in the repo that has permissions
45
+             # 160000, but there is no .gitmodules file.
46
+@@ -219,7 +219,7 @@
47
+             return
48
+ 
49
+         for m in self.submodules:
50
+-            node, ret = self.gitread("git rev-parse %s:%s" % (version, m.path))
51
++            node, ret = self.gitrun('rev-parse', '%s:%s' % (version, m.path))
52
+             if ret:
53
+                 continue
54
+             m.node = node.strip()
55
+@@ -228,15 +228,17 @@
56
+         if full:
57
+             raise error.Abort(_("convert from git does not support --full"))
58
+         self.modecache = {}
59
+-        fh = self.gitopen("git diff-tree -z --root -m -r %s %s" % (
60
+-            self.simopt, version))
61
++        cmd = ['diff-tree','-z', '--root', '-m', '-r'] + self.simopt + [version]
62
++        output, status = self.gitrun(*cmd)
63
++        if status:
64
++            raise error.Abort(_('cannot read changes in %s') % version)
65
+         changes = []
66
+         copies = {}
67
+         seen = set()
68
+         entry = None
69
+         subexists = [False]
70
+         subdeleted = [False]
71
+-        difftree = fh.read().split('\x00')
72
++        difftree = output.split('\x00')
73
+         lcount = len(difftree)
74
+         i = 0
75
+ 
76
+@@ -298,8 +300,6 @@
77
+                     if f != '.gitmodules' and fdest != '.gitmodules':
78
+                         copies[fdest] = f
79
+             entry = None
80
+-        if fh.close():
81
+-            raise error.Abort(_('cannot read changes in %s') % version)
82
+ 
83
+         if subexists[0]:
84
+             if subdeleted[0]:
85
+@@ -345,17 +345,23 @@
86
+         return c
87
+ 
88
+     def numcommits(self):
89
+-        return len([None for _ in self.gitopen('git rev-list --all')])
90
++        output, ret = self.gitrunlines('rev-list', '--all')
91
++        if ret:
92
++            raise error.Abort(_('cannot retrieve number of commits in %s') \
93
++                              % self.path)
94
++        return len(output)
95
+ 
96
+     def gettags(self):
97
+         tags = {}
98
+         alltags = {}
99
+-        fh = self.gitopen('git ls-remote --tags "%s"' % self.path,
100
+-                          err=subprocess.STDOUT)
101
++        output, status = self.gitrunlines('ls-remote', '--tags', self.path)
102
++
103
++        if status:
104
++            raise error.Abort(_('cannot read tags from %s') % self.path)
105
+         prefix = 'refs/tags/'
106
+ 
107
+         # Build complete list of tags, both annotated and bare ones
108
+-        for line in fh:
109
++        for line in output:
110
+             line = line.strip()
111
+             if line.startswith("error:") or line.startswith("fatal:"):
112
+                 raise error.Abort(_('cannot read tags from %s') % self.path)
113
+@@ -363,8 +369,6 @@
114
+             if not tag.startswith(prefix):
115
+                 continue
116
+             alltags[tag[len(prefix):]] = node
117
+-        if fh.close():
118
+-            raise error.Abort(_('cannot read tags from %s') % self.path)
119
+ 
120
+         # Filter out tag objects for annotated tag refs
121
+         for tag in alltags:
122
+@@ -381,18 +385,20 @@
123
+     def getchangedfiles(self, version, i):
124
+         changes = []
125
+         if i is None:
126
+-            fh = self.gitopen("git diff-tree --root -m -r %s" % version)
127
+-            for l in fh:
128
++            output, status = self.gitrunlines('diff-tree', '--root', '-m',
129
++                                              '-r', version)
130
++            if status:
131
++                raise error.Abort(_('cannot read changes in %s') % version)
132
++            for l in output:
133
+                 if "\t" not in l:
134
+                     continue
135
+                 m, f = l[:-1].split("\t")
136
+                 changes.append(f)
137
+         else:
138
+-            fh = self.gitopen('git diff-tree --name-only --root -r %s '
139
+-                              '"%s^%s" --' % (version, version, i + 1))
140
+-            changes = [f.rstrip('\n') for f in fh]
141
+-        if fh.close():
142
+-            raise error.Abort(_('cannot read changes in %s') % version)
143
++            output, status = self.gitrunlines('diff-tree', '--name-only',
144
++                                              '--root', '-r', version,
145
++                                              '%s^%s' % (version, i + 1), '--')
146
++            changes = [f.rstrip('\n') for f in output]
147
+ 
148
+         return changes
149
+ 
150
+@@ -412,8 +418,8 @@
151
+         ])
152
+ 
153
+         try:
154
+-            fh = self.gitopen('git show-ref', err=subprocess.PIPE)
155
+-            for line in fh:
156
++            output, status = self.gitrunlines('show-ref')
157
++            for line in output:
158
+                 line = line.strip()
159
+                 rev, name = line.split(None, 1)
160
+                 # Process each type of branch
161
+--- a/tests/test-convert-git.t	Tue Mar 22 17:05:11 2016 -0700
162
+@@ -714,7 +714,7 @@
163
+   $ COMMIT_OBJ=1c/0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
164
+   $ mv git-repo4/.git/objects/$COMMIT_OBJ git-repo4/.git/objects/$COMMIT_OBJ.tmp
165
+   $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
166
+-  abort: cannot read tags from git-repo4/.git
167
++  abort: cannot retrieve number of commits in git-repo4/.git
168
+   $ mv git-repo4/.git/objects/$COMMIT_OBJ.tmp git-repo4/.git/objects/$COMMIT_OBJ
169
+ damage git repository by renaming a blob object
170
+ 
0 171
new file mode 100644
... ...
@@ -0,0 +1,59 @@
0
+--- a/hgext/convert/git.py	Tue Mar 22 17:05:11 2016 -0700
1
+@@ -30,23 +30,6 @@
2
+     # cannot remove environment variable. Just assume none have
3
+     # both issues.
4
+     if util.safehasattr(os, 'unsetenv'):
5
+-        def gitopen(self, s, err=None):
6
+-            prevgitdir = os.environ.get('GIT_DIR')
7
+-            os.environ['GIT_DIR'] = self.path
8
+-            try:
9
+-                if err == subprocess.PIPE:
10
+-                    (stdin, stdout, stderr) = util.popen3(s)
11
+-                    return stdout
12
+-                elif err == subprocess.STDOUT:
13
+-                    return self.popen_with_stderr(s)
14
+-                else:
15
+-                    return util.popen(s, 'rb')
16
+-            finally:
17
+-                if prevgitdir is None:
18
+-                    del os.environ['GIT_DIR']
19
+-                else:
20
+-                    os.environ['GIT_DIR'] = prevgitdir
21
+-
22
+         def gitpipe(self, s):
23
+             prevgitdir = os.environ.get('GIT_DIR')
24
+             os.environ['GIT_DIR'] = self.path
25
+@@ -59,15 +42,6 @@
26
+                     os.environ['GIT_DIR'] = prevgitdir
27
+ 
28
+     else:
29
+-        def gitopen(self, s, err=None):
30
+-            if err == subprocess.PIPE:
31
+-                (sin, so, se) = util.popen3('GIT_DIR=%s %s' % (self.path, s))
32
+-                return so
33
+-            elif err == subprocess.STDOUT:
34
+-                    return self.popen_with_stderr(s)
35
+-            else:
36
+-                return util.popen('GIT_DIR=%s %s' % (self.path, s), 'rb')
37
+-
38
+         def gitpipe(self, s):
39
+             return util.popen3('GIT_DIR=%s %s' % (self.path, s))
40
+ 
41
+@@ -86,16 +60,6 @@
42
+     def gitrunlines(self, *args, **kwargs):
43
+         return self._gitcmd(self.runlines, *args, **kwargs)
44
+ 
45
+-    def popen_with_stderr(self, s):
46
+-        p = subprocess.Popen(s, shell=True, bufsize=-1,
47
+-                             close_fds=util.closefds,
48
+-                             stdin=subprocess.PIPE,
49
+-                             stdout=subprocess.PIPE,
50
+-                             stderr=subprocess.STDOUT,
51
+-                             universal_newlines=False,
52
+-                             env=None)
53
+-        return p.stdout
54
+-
55
+     def gitread(self, s):
56
+         fh = self.gitopen(s)
57
+         data = fh.read()
0 58
new file mode 100644
... ...
@@ -0,0 +1,55 @@
0
+--- a/hgext/convert/common.py	Tue Mar 22 17:05:11 2016 -0700
1
+@@ -341,6 +341,9 @@
2
+     def _run2(self, cmd, *args, **kwargs):
3
+         return self._dorun(util.popen2, cmd, *args, **kwargs)
4
+ 
5
++    def _run3(self, cmd, *args, **kwargs):
6
++        return self._dorun(util.popen3, cmd, *args, **kwargs)
7
++
8
+     def _dorun(self, openfunc, cmd,  *args, **kwargs):
9
+         cmdline = self._cmdline(cmd, *args, **kwargs)
10
+         self.ui.debug('running: %s\n' % (cmdline,))
11
+--- a/hgext/convert/git.py	Tue Mar 22 17:05:11 2016 -0700
12
+@@ -29,21 +29,6 @@
13
+     # Windows does not support GIT_DIR= construct while other systems
14
+     # cannot remove environment variable. Just assume none have
15
+     # both issues.
16
+-    if util.safehasattr(os, 'unsetenv'):
17
+-        def gitpipe(self, s):
18
+-            prevgitdir = os.environ.get('GIT_DIR')
19
+-            os.environ['GIT_DIR'] = self.path
20
+-            try:
21
+-                return util.popen3(s)
22
+-            finally:
23
+-                if prevgitdir is None:
24
+-                    del os.environ['GIT_DIR']
25
+-                else:
26
+-                    os.environ['GIT_DIR'] = prevgitdir
27
+-
28
+-    else:
29
+-        def gitpipe(self, s):
30
+-            return util.popen3('GIT_DIR=%s %s' % (self.path, s))
31
+ 
32
+     def _gitcmd(self, cmd, *args, **kwargs):
33
+         return cmd('--git-dir=%s' % self.path, *args, **kwargs)
34
+@@ -60,6 +45,9 @@
35
+     def gitrunlines(self, *args, **kwargs):
36
+         return self._gitcmd(self.runlines, *args, **kwargs)
37
+ 
38
++    def gitpipe(self, *args, **kwargs):
39
++        return self._gitcmd(self._run3, *args, **kwargs)
40
++
41
+     def gitread(self, s):
42
+         fh = self.gitopen(s)
43
+         data = fh.read()
44
+@@ -92,7 +80,7 @@
45
+         self.path = path
46
+         self.submodules = []
47
+ 
48
+-        self.catfilepipe = self.gitpipe('git cat-file --batch')
49
++        self.catfilepipe = self.gitpipe('cat-file', '--batch')
50
+ 
51
+     def after(self):
52
+         for f in self.catfilepipe:
0 53
new file mode 100644
... ...
@@ -0,0 +1,23 @@
0
+--- a/tests/test-convert-git.t	Tue Mar 22 17:05:11 2016 -0700
1
+@@ -729,3 +729,20 @@
2
+   $ mv git-repo4/.git/objects/$TREE_OBJ git-repo4/.git/objects/$TREE_OBJ.tmp
3
+   $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
4
+   abort: cannot read changes in 1c0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
5
++
6
++test for escaping the repo name (CVE-2016-3069)
7
++
8
++  $ git init '`echo pwned >COMMAND-INJECTION`'
9
++  Initialized empty Git repository in $TESTTMP/`echo pwned >COMMAND-INJECTION`/.git/
10
++  $ cd '`echo pwned >COMMAND-INJECTION`'
11
++  $ git commit -q --allow-empty -m 'empty'
12
++  $ cd ..
13
++  $ hg convert '`echo pwned >COMMAND-INJECTION`' 'converted'
14
++  initializing destination converted repository
15
++  scanning source...
16
++  sorting...
17
++  converting...
18
++  0 empty
19
++  updating bookmarks
20
++  $ test -f COMMAND-INJECTION
21
++  [1]
0 22
new file mode 100644
... ...
@@ -0,0 +1,62 @@
0
+--- a/hgext/convert/git.py  Sun May 01 13:52:26 2016 -0500
1
+@@ -57,6 +57,10 @@ class convert_git(converter_source, commandline):
2
+         super(convert_git, self).__init__(ui, path, revs=revs)
3
+         commandline.__init__(self, ui, 'git')
4
+ 
5
++        # Pass an absolute path to git to prevent from ever being interpreted
6
++        # as a URL
7
++        path = os.path.abspath(path)
8
++
9
+         if os.path.isdir(path + "/.git"):
10
+             path += "/.git"
11
+         if not os.path.exists(path + "/objects"):
12
+
13
+--- a/tests/test-convert-git.t  Sun May 01 13:52:26 2016 -0500
14
+@@ -714,7 +714,7 @@
15
+   $ COMMIT_OBJ=1c/0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
16
+   $ mv git-repo4/.git/objects/$COMMIT_OBJ git-repo4/.git/objects/$COMMIT_OBJ.tmp
17
+   $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
18
+-  abort: cannot retrieve number of commits in git-repo4/.git
19
++  abort: cannot retrieve number of commits in $TESTTMP/git-repo4/.git
20
+   $ mv git-repo4/.git/objects/$COMMIT_OBJ.tmp git-repo4/.git/objects/$COMMIT_OBJ
21
+ damage git repository by renaming a blob object
22
+ 
23
+@@ -746,3 +746,21 @@ test for escaping the repo name (CVE-2016-3069)
24
+   updating bookmarks
25
+   $ test -f COMMAND-INJECTION
26
+   [1]
27
++
28
++test for safely passing paths to git (CVE-2016-3105)
29
++
30
++  $ git init 'ext::sh -c echo% pwned% >GIT-EXT-COMMAND-INJECTION% #'
31
++  Initialized empty Git repository in $TESTTMP/ext::sh -c echo% pwned% >GIT-EXT-COMMAND-INJECTION% #/.git/
32
++  $ cd 'ext::sh -c echo% pwned% >GIT-EXT-COMMAND-INJECTION% #'
33
++  $ git commit -q --allow-empty -m 'empty'
34
++  $ cd ..
35
++  $ hg convert 'ext::sh -c echo% pwned% >GIT-EXT-COMMAND-INJECTION% #' 'converted-git-ext'
36
++  initializing destination converted-git-ext repository
37
++  scanning source...
38
++  sorting...
39
++  converting...
40
++  0 empty
41
++  updating bookmarks
42
++  $ test -f GIT-EXT-COMMAND-INJECTION
43
++  [1]
44
++
45
+
46
+
47
+--- a/tests/test-convert.t  Sun May 01 13:52:26 2016 -0500
48
+@@ -422,7 +422,7 @@
49
+   assuming destination emptydir-hg
50
+   initializing destination emptydir-hg repository
51
+   emptydir does not look like a CVS checkout
52
+-  emptydir does not look like a Git repository
53
++  $TESTTMP/emptydir does not look like a Git repository
54
+   emptydir does not look like a Subversion repository
55
+   emptydir is not a local Mercurial repository
56
+   emptydir does not look like a darcs repository
57
+
58
+
... ...
@@ -1,23 +1,37 @@
1
-Summary:	Mercurial-3.1.2
2
-Name:		mercurial
3
-Version:	3.7.1
4
-Release:	4%{?dist}
5
-License:	GPLv2+
6
-URL:		https://www.ruby-lang.org/en/
7
-Group:		System Environment/Security
8
-Vendor:		VMware, Inc.
1
+Summary:    A free, distributed source control management tool.
2
+Name:       mercurial
3
+Version:    3.7.1
4
+Release:    5%{?dist}
5
+License:    GPLv2+
6
+URL:        https://www.ruby-lang.org/en/
7
+Group:      System Environment/Security
8
+Vendor:     VMware, Inc.
9 9
 Distribution: Photon
10
-Source0:	http://mercurial.selenic.com/release/%{name}-%{version}.tar.gz
10
+Source0:    http://mercurial.selenic.com/release/%{name}-%{version}.tar.gz
11 11
 %define sha1 mercurial=8ce55b297c6a62e987657498746eeca870301ffb
12
-BuildRequires:	python2-devel
13
-BuildRequires:	python2-libs
14
-Requires:	python2
12
+Patch0:   hg-CVE-2016-3068.patch
13
+Patch1:   hg-CVE-2016-3069-1.patch
14
+Patch2:   hg-CVE-2016-3069-2.patch
15
+Patch3:   hg-CVE-2016-3069-3.patch
16
+Patch4:   hg-CVE-2016-3069-4.patch
17
+Patch5:   hg-CVE-2016-3069-5.patch
18
+Patch6:   hg-CVE-2016-3105.patch
19
+BuildRequires:  python2-devel
20
+BuildRequires:  python2-libs
21
+Requires:   python2
15 22
 %description
16 23
 Mercurial is a distributed source control management tool similar to Git and Bazaar.
17 24
 Mercurial is written in Python and is used by projects such as Mozilla and Vim.
18 25
 
19 26
 %prep
20 27
 %setup -q
28
+%patch0 -p1
29
+%patch1 -p1
30
+%patch2 -p1
31
+%patch3 -p1
32
+%patch4 -p1
33
+%patch5 -p1
34
+%patch6 -p1
21 35
 %build
22 36
 make build
23 37
 %install
... ...
@@ -63,19 +77,21 @@ rm -rf %{buildroot}/*
63 63
 %exclude /var/opt/%{name}-%{version}/contrib/plan9
64 64
 %exclude /var/opt/%{name}-%{version}/build/temp.*
65 65
 %changelog
66
-*       Fri Oct 07 2016 ChangLee <changlee@vmware.com> 3.7.1-4
67
--       Modified %check
68
-*	Tue May 24 2016 Priyesh Padmavilasom <ppadmavilasom@vmware.com> 3.7.1-3
69
--	GA - Bump release of all rpms
70
-*	Wed May 04 2016 Anish Swaminathan <anishs@vmware.com> 3.7.1-2
71
--	Edit postun script.
72
-*       Thu Feb 25 2016 Kumar Kaushik <kaushikk@vmware.com> 3.7.1-1
73
--       Updating Version.
74
-*	Wed Dec 09 2015 Anish Swaminathan <anishs@vmware.com> 3.1.2-4
75
--	Edit post script.
76
-*	Mon Nov 16 2015 Sharath George <sharathg@vmware.com> 3.1.2-3
77
--	Change path to /var/opt.
78
-*	Tue Jun 30 2015 Alexey Makhalov <amakhalov@vmware.com> 3.1.2-2
79
--	/etc/profile.d permission fix
80
-*	Mon Oct 13 2014 Divya Thaluru <dthaluru@vmware.com> 3.1.2-1
81
--	Initial build.	First version
66
+*   Tue Nov 22 2016 Xiaolin Li <xiaolinl@vmware.com> 3.7.1-5
67
+-   Apply patches for CVE-2016-3068, CVE-2016-3069, CVE-2016-3105
68
+*   Fri Oct 07 2016 ChangLee <changlee@vmware.com> 3.7.1-4
69
+-   Modified %check
70
+*   Tue May 24 2016 Priyesh Padmavilasom <ppadmavilasom@vmware.com> 3.7.1-3
71
+-   GA - Bump release of all rpms
72
+*   Wed May 04 2016 Anish Swaminathan <anishs@vmware.com> 3.7.1-2
73
+-   Edit postun script.
74
+*   Thu Feb 25 2016 Kumar Kaushik <kaushikk@vmware.com> 3.7.1-1
75
+-   Updating Version.
76
+*   Wed Dec 09 2015 Anish Swaminathan <anishs@vmware.com> 3.1.2-4
77
+-   Edit post script.
78
+*   Mon Nov 16 2015 Sharath George <sharathg@vmware.com> 3.1.2-3
79
+-   Change path to /var/opt.
80
+*   Tue Jun 30 2015 Alexey Makhalov <amakhalov@vmware.com> 3.1.2-2
81
+-   /etc/profile.d permission fix
82
+*   Mon Oct 13 2014 Divya Thaluru <dthaluru@vmware.com> 3.1.2-1
83
+-   Initial build.  First version